diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-03-21 16:14:16 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-03-21 16:14:16 -0400 |
commit | 2c856e14dad8cb1b085ae1f30c5e125c6d46019b (patch) | |
tree | 0b0067f6b83a536e7edb41d400a50c383c26e686 | |
parent | d34687ab97731b3a707106f78756342b61f46dbc (diff) | |
parent | 357b565d5d52b2dc2a51390eb8f887a9caa8597f (diff) |
Merge tag 'arm64-perf' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux
Pull arm[64] perf updates from Will Deacon:
"I have another mixed bag of ARM-related perf patches here.
It's about 25% CPU and 75% interconnect, but with drivers/bus/
languishing without an obvious maintainer or tree, Olof and I agreed
to keep all of these PMU patches together. I suspect a whole load of
code from drivers/bus/arm-* can be moved under drivers/perf/, so
that's on the radar for the future.
Summary:
- Initial support for ARMv8.1 CPU PMUs
- Support for the CPU PMU in Cavium ThunderX
- CPU PMU support for systems running 32-bit Linux in secure mode
- Support for the system PMU in ARM CCI-550 (Cache Coherent Interconnect)"
* tag 'arm64-perf' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux: (26 commits)
drivers/perf: arm_pmu: avoid NULL dereference when not using devicetree
arm64: perf: Extend ARMV8_EVTYPE_MASK to include PMCR.LC
arm-cci: remove unused variable
arm-cci: don't return value from void function
arm-cci: make private functions static
arm-cci: CoreLink CCI-550 PMU driver
arm-cci500: Rearrange PMU driver for code sharing with CCI-550 PMU
arm-cci: CCI-500: Work around PMU counter writes
arm-cci: Provide hook for writing to PMU counters
arm-cci: Add helper to enable PMU without synchornising counters
arm-cci: Add routines to save/restore all counters
arm-cci: Get the status of a counter
arm-cci: write_counter: Remove redundant check
arm-cci: Delay PMU counter writes to pmu::pmu_enable
arm-cci: Refactor CCI PMU enable/disable methods
arm-cci: Group writes to counter
arm-cci: fix handling cpumask_any_but return value
arm-cci: simplify sysfs attr handling
drivers/perf: arm_pmu: implement CPU_PM notifier
arm64: dts: Add Cavium ThunderX specific PMU
...
-rw-r--r-- | Documentation/devicetree/bindings/arm/cci.txt | 2 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/arm/pmu.txt | 11 | ||||
-rw-r--r-- | arch/arm/kernel/perf_event_v7.c | 13 | ||||
-rw-r--r-- | arch/arm64/boot/dts/cavium/thunder-88xx.dtsi | 5 | ||||
-rw-r--r-- | arch/arm64/kernel/perf_event.c | 122 | ||||
-rw-r--r-- | drivers/bus/Kconfig | 10 | ||||
-rw-r--r-- | drivers/bus/arm-cci.c | 621 | ||||
-rw-r--r-- | drivers/perf/arm_pmu.c | 109 | ||||
-rw-r--r-- | include/linux/perf/arm_pmu.h | 2 |
9 files changed, 667 insertions, 228 deletions
diff --git a/Documentation/devicetree/bindings/arm/cci.txt b/Documentation/devicetree/bindings/arm/cci.txt index aef1d200a9b2..a1a5a7ecc2fb 100644 --- a/Documentation/devicetree/bindings/arm/cci.txt +++ b/Documentation/devicetree/bindings/arm/cci.txt | |||
@@ -34,6 +34,7 @@ specific to ARM. | |||
34 | Definition: must contain one of the following: | 34 | Definition: must contain one of the following: |
35 | "arm,cci-400" | 35 | "arm,cci-400" |
36 | "arm,cci-500" | 36 | "arm,cci-500" |
37 | "arm,cci-550" | ||
37 | 38 | ||
38 | - reg | 39 | - reg |
39 | Usage: required | 40 | Usage: required |
@@ -101,6 +102,7 @@ specific to ARM. | |||
101 | "arm,cci-400-pmu" - DEPRECATED, permitted only where OS has | 102 | "arm,cci-400-pmu" - DEPRECATED, permitted only where OS has |
102 | secure acces to CCI registers | 103 | secure acces to CCI registers |
103 | "arm,cci-500-pmu,r0" | 104 | "arm,cci-500-pmu,r0" |
105 | "arm,cci-550-pmu,r0" | ||
104 | - reg: | 106 | - reg: |
105 | Usage: required | 107 | Usage: required |
106 | Value type: Integer cells. A register entry, expressed | 108 | Value type: Integer cells. A register entry, expressed |
diff --git a/Documentation/devicetree/bindings/arm/pmu.txt b/Documentation/devicetree/bindings/arm/pmu.txt index 56518839f52a..6eb73be9433e 100644 --- a/Documentation/devicetree/bindings/arm/pmu.txt +++ b/Documentation/devicetree/bindings/arm/pmu.txt | |||
@@ -25,6 +25,7 @@ Required properties: | |||
25 | "qcom,scorpion-pmu" | 25 | "qcom,scorpion-pmu" |
26 | "qcom,scorpion-mp-pmu" | 26 | "qcom,scorpion-mp-pmu" |
27 | "qcom,krait-pmu" | 27 | "qcom,krait-pmu" |
28 | "cavium,thunder-pmu" | ||
28 | - interrupts : 1 combined interrupt or 1 per core. If the interrupt is a per-cpu | 29 | - interrupts : 1 combined interrupt or 1 per core. If the interrupt is a per-cpu |
29 | interrupt (PPI) then 1 interrupt should be specified. | 30 | interrupt (PPI) then 1 interrupt should be specified. |
30 | 31 | ||
@@ -46,6 +47,16 @@ Optional properties: | |||
46 | - qcom,no-pc-write : Indicates that this PMU doesn't support the 0xc and 0xd | 47 | - qcom,no-pc-write : Indicates that this PMU doesn't support the 0xc and 0xd |
47 | events. | 48 | events. |
48 | 49 | ||
50 | - secure-reg-access : Indicates that the ARMv7 Secure Debug Enable Register | ||
51 | (SDER) is accessible. This will cause the driver to do | ||
52 | any setup required that is only possible in ARMv7 secure | ||
53 | state. If not present the ARMv7 SDER will not be touched, | ||
54 | which means the PMU may fail to operate unless external | ||
55 | code (bootloader or security monitor) has performed the | ||
56 | appropriate initialisation. Note that this property is | ||
57 | not valid for non-ARMv7 CPUs or ARMv7 CPUs booting Linux | ||
58 | in Non-secure state. | ||
59 | |||
49 | Example: | 60 | Example: |
50 | 61 | ||
51 | pmu { | 62 | pmu { |
diff --git a/arch/arm/kernel/perf_event_v7.c b/arch/arm/kernel/perf_event_v7.c index 4152158f6e6a..15063851cd10 100644 --- a/arch/arm/kernel/perf_event_v7.c +++ b/arch/arm/kernel/perf_event_v7.c | |||
@@ -712,6 +712,11 @@ static const struct attribute_group *armv7_pmuv2_attr_groups[] = { | |||
712 | #define ARMV7_EXCLUDE_USER (1 << 30) | 712 | #define ARMV7_EXCLUDE_USER (1 << 30) |
713 | #define ARMV7_INCLUDE_HYP (1 << 27) | 713 | #define ARMV7_INCLUDE_HYP (1 << 27) |
714 | 714 | ||
715 | /* | ||
716 | * Secure debug enable reg | ||
717 | */ | ||
718 | #define ARMV7_SDER_SUNIDEN BIT(1) /* Permit non-invasive debug */ | ||
719 | |||
715 | static inline u32 armv7_pmnc_read(void) | 720 | static inline u32 armv7_pmnc_read(void) |
716 | { | 721 | { |
717 | u32 val; | 722 | u32 val; |
@@ -1094,7 +1099,13 @@ static int armv7pmu_set_event_filter(struct hw_perf_event *event, | |||
1094 | static void armv7pmu_reset(void *info) | 1099 | static void armv7pmu_reset(void *info) |
1095 | { | 1100 | { |
1096 | struct arm_pmu *cpu_pmu = (struct arm_pmu *)info; | 1101 | struct arm_pmu *cpu_pmu = (struct arm_pmu *)info; |
1097 | u32 idx, nb_cnt = cpu_pmu->num_events; | 1102 | u32 idx, nb_cnt = cpu_pmu->num_events, val; |
1103 | |||
1104 | if (cpu_pmu->secure_access) { | ||
1105 | asm volatile("mrc p15, 0, %0, c1, c1, 1" : "=r" (val)); | ||
1106 | val |= ARMV7_SDER_SUNIDEN; | ||
1107 | asm volatile("mcr p15, 0, %0, c1, c1, 1" : : "r" (val)); | ||
1108 | } | ||
1098 | 1109 | ||
1099 | /* The counter and interrupt enable registers are unknown at reset. */ | 1110 | /* The counter and interrupt enable registers are unknown at reset. */ |
1100 | for (idx = ARMV7_IDX_CYCLE_COUNTER; idx < nb_cnt; ++idx) { | 1111 | for (idx = ARMV7_IDX_CYCLE_COUNTER; idx < nb_cnt; ++idx) { |
diff --git a/arch/arm64/boot/dts/cavium/thunder-88xx.dtsi b/arch/arm64/boot/dts/cavium/thunder-88xx.dtsi index 9cb7cf94284a..2eb9b225f0bc 100644 --- a/arch/arm64/boot/dts/cavium/thunder-88xx.dtsi +++ b/arch/arm64/boot/dts/cavium/thunder-88xx.dtsi | |||
@@ -360,6 +360,11 @@ | |||
360 | <1 10 0xff01>; | 360 | <1 10 0xff01>; |
361 | }; | 361 | }; |
362 | 362 | ||
363 | pmu { | ||
364 | compatible = "cavium,thunder-pmu", "arm,armv8-pmuv3"; | ||
365 | interrupts = <1 7 4>; | ||
366 | }; | ||
367 | |||
363 | soc { | 368 | soc { |
364 | compatible = "simple-bus"; | 369 | compatible = "simple-bus"; |
365 | #address-cells = <2>; | 370 | #address-cells = <2>; |
diff --git a/arch/arm64/kernel/perf_event.c b/arch/arm64/kernel/perf_event.c index 1b52269ffa87..767c4f6e1f5b 100644 --- a/arch/arm64/kernel/perf_event.c +++ b/arch/arm64/kernel/perf_event.c | |||
@@ -88,16 +88,25 @@ | |||
88 | #define ARMV8_PMUV3_PERFCTR_L2D_TLB 0x2F | 88 | #define ARMV8_PMUV3_PERFCTR_L2D_TLB 0x2F |
89 | #define ARMV8_PMUV3_PERFCTR_L21_TLB 0x30 | 89 | #define ARMV8_PMUV3_PERFCTR_L21_TLB 0x30 |
90 | 90 | ||
91 | /* ARMv8 implementation defined event types. */ | ||
92 | #define ARMV8_IMPDEF_PERFCTR_L1_DCACHE_ACCESS_LD 0x40 | ||
93 | #define ARMV8_IMPDEF_PERFCTR_L1_DCACHE_ACCESS_ST 0x41 | ||
94 | #define ARMV8_IMPDEF_PERFCTR_L1_DCACHE_REFILL_LD 0x42 | ||
95 | #define ARMV8_IMPDEF_PERFCTR_L1_DCACHE_REFILL_ST 0x43 | ||
96 | #define ARMV8_IMPDEF_PERFCTR_DTLB_REFILL_LD 0x4C | ||
97 | #define ARMV8_IMPDEF_PERFCTR_DTLB_REFILL_ST 0x4D | ||
98 | #define ARMV8_IMPDEF_PERFCTR_DTLB_ACCESS_LD 0x4E | ||
99 | #define ARMV8_IMPDEF_PERFCTR_DTLB_ACCESS_ST 0x4F | ||
100 | |||
91 | /* ARMv8 Cortex-A53 specific event types. */ | 101 | /* ARMv8 Cortex-A53 specific event types. */ |
92 | #define ARMV8_A53_PERFCTR_PREFETCH_LINEFILL 0xC2 | 102 | #define ARMV8_A53_PERFCTR_PREFETCH_LINEFILL 0xC2 |
93 | 103 | ||
94 | /* ARMv8 Cortex-A57 and Cortex-A72 specific event types. */ | 104 | /* ARMv8 Cavium ThunderX specific event types. */ |
95 | #define ARMV8_A57_PERFCTR_L1_DCACHE_ACCESS_LD 0x40 | 105 | #define ARMV8_THUNDER_PERFCTR_L1_DCACHE_MISS_ST 0xE9 |
96 | #define ARMV8_A57_PERFCTR_L1_DCACHE_ACCESS_ST 0x41 | 106 | #define ARMV8_THUNDER_PERFCTR_L1_DCACHE_PREF_ACCESS 0xEA |
97 | #define ARMV8_A57_PERFCTR_L1_DCACHE_REFILL_LD 0x42 | 107 | #define ARMV8_THUNDER_PERFCTR_L1_DCACHE_PREF_MISS 0xEB |
98 | #define ARMV8_A57_PERFCTR_L1_DCACHE_REFILL_ST 0x43 | 108 | #define ARMV8_THUNDER_PERFCTR_L1_ICACHE_PREF_ACCESS 0xEC |
99 | #define ARMV8_A57_PERFCTR_DTLB_REFILL_LD 0x4c | 109 | #define ARMV8_THUNDER_PERFCTR_L1_ICACHE_PREF_MISS 0xED |
100 | #define ARMV8_A57_PERFCTR_DTLB_REFILL_ST 0x4d | ||
101 | 110 | ||
102 | /* PMUv3 HW events mapping. */ | 111 | /* PMUv3 HW events mapping. */ |
103 | static const unsigned armv8_pmuv3_perf_map[PERF_COUNT_HW_MAX] = { | 112 | static const unsigned armv8_pmuv3_perf_map[PERF_COUNT_HW_MAX] = { |
@@ -132,6 +141,18 @@ static const unsigned armv8_a57_perf_map[PERF_COUNT_HW_MAX] = { | |||
132 | [PERF_COUNT_HW_BUS_CYCLES] = ARMV8_PMUV3_PERFCTR_BUS_CYCLES, | 141 | [PERF_COUNT_HW_BUS_CYCLES] = ARMV8_PMUV3_PERFCTR_BUS_CYCLES, |
133 | }; | 142 | }; |
134 | 143 | ||
144 | static const unsigned armv8_thunder_perf_map[PERF_COUNT_HW_MAX] = { | ||
145 | PERF_MAP_ALL_UNSUPPORTED, | ||
146 | [PERF_COUNT_HW_CPU_CYCLES] = ARMV8_PMUV3_PERFCTR_CLOCK_CYCLES, | ||
147 | [PERF_COUNT_HW_INSTRUCTIONS] = ARMV8_PMUV3_PERFCTR_INSTR_EXECUTED, | ||
148 | [PERF_COUNT_HW_CACHE_REFERENCES] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS, | ||
149 | [PERF_COUNT_HW_CACHE_MISSES] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL, | ||
150 | [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV8_PMUV3_PERFCTR_PC_WRITE, | ||
151 | [PERF_COUNT_HW_BRANCH_MISSES] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED, | ||
152 | [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = ARMV8_PMUV3_PERFCTR_STALL_FRONTEND, | ||
153 | [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = ARMV8_PMUV3_PERFCTR_STALL_BACKEND, | ||
154 | }; | ||
155 | |||
135 | static const unsigned armv8_pmuv3_perf_cache_map[PERF_COUNT_HW_CACHE_MAX] | 156 | static const unsigned armv8_pmuv3_perf_cache_map[PERF_COUNT_HW_CACHE_MAX] |
136 | [PERF_COUNT_HW_CACHE_OP_MAX] | 157 | [PERF_COUNT_HW_CACHE_OP_MAX] |
137 | [PERF_COUNT_HW_CACHE_RESULT_MAX] = { | 158 | [PERF_COUNT_HW_CACHE_RESULT_MAX] = { |
@@ -175,16 +196,46 @@ static const unsigned armv8_a57_perf_cache_map[PERF_COUNT_HW_CACHE_MAX] | |||
175 | [PERF_COUNT_HW_CACHE_RESULT_MAX] = { | 196 | [PERF_COUNT_HW_CACHE_RESULT_MAX] = { |
176 | PERF_CACHE_MAP_ALL_UNSUPPORTED, | 197 | PERF_CACHE_MAP_ALL_UNSUPPORTED, |
177 | 198 | ||
178 | [C(L1D)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_A57_PERFCTR_L1_DCACHE_ACCESS_LD, | 199 | [C(L1D)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_L1_DCACHE_ACCESS_LD, |
179 | [C(L1D)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_A57_PERFCTR_L1_DCACHE_REFILL_LD, | 200 | [C(L1D)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_IMPDEF_PERFCTR_L1_DCACHE_REFILL_LD, |
180 | [C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_A57_PERFCTR_L1_DCACHE_ACCESS_ST, | 201 | [C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_L1_DCACHE_ACCESS_ST, |
181 | [C(L1D)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_A57_PERFCTR_L1_DCACHE_REFILL_ST, | 202 | [C(L1D)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_IMPDEF_PERFCTR_L1_DCACHE_REFILL_ST, |
182 | 203 | ||
183 | [C(L1I)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_L1_ICACHE_ACCESS, | 204 | [C(L1I)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_L1_ICACHE_ACCESS, |
184 | [C(L1I)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_L1_ICACHE_REFILL, | 205 | [C(L1I)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_L1_ICACHE_REFILL, |
185 | 206 | ||
186 | [C(DTLB)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_A57_PERFCTR_DTLB_REFILL_LD, | 207 | [C(DTLB)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_IMPDEF_PERFCTR_DTLB_REFILL_LD, |
187 | [C(DTLB)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_A57_PERFCTR_DTLB_REFILL_ST, | 208 | [C(DTLB)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_IMPDEF_PERFCTR_DTLB_REFILL_ST, |
209 | |||
210 | [C(ITLB)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_ITLB_REFILL, | ||
211 | |||
212 | [C(BPU)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_PRED, | ||
213 | [C(BPU)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED, | ||
214 | [C(BPU)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_PRED, | ||
215 | [C(BPU)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED, | ||
216 | }; | ||
217 | |||
218 | static const unsigned armv8_thunder_perf_cache_map[PERF_COUNT_HW_CACHE_MAX] | ||
219 | [PERF_COUNT_HW_CACHE_OP_MAX] | ||
220 | [PERF_COUNT_HW_CACHE_RESULT_MAX] = { | ||
221 | PERF_CACHE_MAP_ALL_UNSUPPORTED, | ||
222 | |||
223 | [C(L1D)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_L1_DCACHE_ACCESS_LD, | ||
224 | [C(L1D)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_IMPDEF_PERFCTR_L1_DCACHE_REFILL_LD, | ||
225 | [C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_L1_DCACHE_ACCESS_ST, | ||
226 | [C(L1D)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_THUNDER_PERFCTR_L1_DCACHE_MISS_ST, | ||
227 | [C(L1D)][C(OP_PREFETCH)][C(RESULT_ACCESS)] = ARMV8_THUNDER_PERFCTR_L1_DCACHE_PREF_ACCESS, | ||
228 | [C(L1D)][C(OP_PREFETCH)][C(RESULT_MISS)] = ARMV8_THUNDER_PERFCTR_L1_DCACHE_PREF_MISS, | ||
229 | |||
230 | [C(L1I)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_L1_ICACHE_ACCESS, | ||
231 | [C(L1I)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_L1_ICACHE_REFILL, | ||
232 | [C(L1I)][C(OP_PREFETCH)][C(RESULT_ACCESS)] = ARMV8_THUNDER_PERFCTR_L1_ICACHE_PREF_ACCESS, | ||
233 | [C(L1I)][C(OP_PREFETCH)][C(RESULT_MISS)] = ARMV8_THUNDER_PERFCTR_L1_ICACHE_PREF_MISS, | ||
234 | |||
235 | [C(DTLB)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_DTLB_ACCESS_LD, | ||
236 | [C(DTLB)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_IMPDEF_PERFCTR_DTLB_REFILL_LD, | ||
237 | [C(DTLB)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_DTLB_ACCESS_ST, | ||
238 | [C(DTLB)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_IMPDEF_PERFCTR_DTLB_REFILL_ST, | ||
188 | 239 | ||
189 | [C(ITLB)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_ITLB_REFILL, | 240 | [C(ITLB)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_ITLB_REFILL, |
190 | 241 | ||
@@ -325,7 +376,6 @@ static const struct attribute_group *armv8_pmuv3_attr_groups[] = { | |||
325 | NULL, | 376 | NULL, |
326 | }; | 377 | }; |
327 | 378 | ||
328 | |||
329 | /* | 379 | /* |
330 | * Perf Events' indices | 380 | * Perf Events' indices |
331 | */ | 381 | */ |
@@ -356,9 +406,10 @@ static const struct attribute_group *armv8_pmuv3_attr_groups[] = { | |||
356 | #define ARMV8_PMCR_D (1 << 3) /* CCNT counts every 64th cpu cycle */ | 406 | #define ARMV8_PMCR_D (1 << 3) /* CCNT counts every 64th cpu cycle */ |
357 | #define ARMV8_PMCR_X (1 << 4) /* Export to ETM */ | 407 | #define ARMV8_PMCR_X (1 << 4) /* Export to ETM */ |
358 | #define ARMV8_PMCR_DP (1 << 5) /* Disable CCNT if non-invasive debug*/ | 408 | #define ARMV8_PMCR_DP (1 << 5) /* Disable CCNT if non-invasive debug*/ |
409 | #define ARMV8_PMCR_LC (1 << 6) /* Overflow on 64 bit cycle counter */ | ||
359 | #define ARMV8_PMCR_N_SHIFT 11 /* Number of counters supported */ | 410 | #define ARMV8_PMCR_N_SHIFT 11 /* Number of counters supported */ |
360 | #define ARMV8_PMCR_N_MASK 0x1f | 411 | #define ARMV8_PMCR_N_MASK 0x1f |
361 | #define ARMV8_PMCR_MASK 0x3f /* Mask for writable bits */ | 412 | #define ARMV8_PMCR_MASK 0x7f /* Mask for writable bits */ |
362 | 413 | ||
363 | /* | 414 | /* |
364 | * PMOVSR: counters overflow flag status reg | 415 | * PMOVSR: counters overflow flag status reg |
@@ -369,8 +420,8 @@ static const struct attribute_group *armv8_pmuv3_attr_groups[] = { | |||
369 | /* | 420 | /* |
370 | * PMXEVTYPER: Event selection reg | 421 | * PMXEVTYPER: Event selection reg |
371 | */ | 422 | */ |
372 | #define ARMV8_EVTYPE_MASK 0xc80003ff /* Mask for writable bits */ | 423 | #define ARMV8_EVTYPE_MASK 0xc800ffff /* Mask for writable bits */ |
373 | #define ARMV8_EVTYPE_EVENT 0x3ff /* Mask for EVENT bits */ | 424 | #define ARMV8_EVTYPE_EVENT 0xffff /* Mask for EVENT bits */ |
374 | 425 | ||
375 | /* | 426 | /* |
376 | * Event filters for PMUv3 | 427 | * Event filters for PMUv3 |
@@ -445,9 +496,16 @@ static inline void armv8pmu_write_counter(struct perf_event *event, u32 value) | |||
445 | if (!armv8pmu_counter_valid(cpu_pmu, idx)) | 496 | if (!armv8pmu_counter_valid(cpu_pmu, idx)) |
446 | pr_err("CPU%u writing wrong counter %d\n", | 497 | pr_err("CPU%u writing wrong counter %d\n", |
447 | smp_processor_id(), idx); | 498 | smp_processor_id(), idx); |
448 | else if (idx == ARMV8_IDX_CYCLE_COUNTER) | 499 | else if (idx == ARMV8_IDX_CYCLE_COUNTER) { |
449 | asm volatile("msr pmccntr_el0, %0" :: "r" (value)); | 500 | /* |
450 | else if (armv8pmu_select_counter(idx) == idx) | 501 | * Set the upper 32bits as this is a 64bit counter but we only |
502 | * count using the lower 32bits and we want an interrupt when | ||
503 | * it overflows. | ||
504 | */ | ||
505 | u64 value64 = 0xffffffff00000000ULL | value; | ||
506 | |||
507 | asm volatile("msr pmccntr_el0, %0" :: "r" (value64)); | ||
508 | } else if (armv8pmu_select_counter(idx) == idx) | ||
451 | asm volatile("msr pmxevcntr_el0, %0" :: "r" (value)); | 509 | asm volatile("msr pmxevcntr_el0, %0" :: "r" (value)); |
452 | } | 510 | } |
453 | 511 | ||
@@ -722,8 +780,11 @@ static void armv8pmu_reset(void *info) | |||
722 | armv8pmu_disable_intens(idx); | 780 | armv8pmu_disable_intens(idx); |
723 | } | 781 | } |
724 | 782 | ||
725 | /* Initialize & Reset PMNC: C and P bits. */ | 783 | /* |
726 | armv8pmu_pmcr_write(ARMV8_PMCR_P | ARMV8_PMCR_C); | 784 | * Initialize & Reset PMNC. Request overflow interrupt for |
785 | * 64 bit cycle counter but cheat in armv8pmu_write_counter(). | ||
786 | */ | ||
787 | armv8pmu_pmcr_write(ARMV8_PMCR_P | ARMV8_PMCR_C | ARMV8_PMCR_LC); | ||
727 | } | 788 | } |
728 | 789 | ||
729 | static int armv8_pmuv3_map_event(struct perf_event *event) | 790 | static int armv8_pmuv3_map_event(struct perf_event *event) |
@@ -747,6 +808,13 @@ static int armv8_a57_map_event(struct perf_event *event) | |||
747 | ARMV8_EVTYPE_EVENT); | 808 | ARMV8_EVTYPE_EVENT); |
748 | } | 809 | } |
749 | 810 | ||
811 | static int armv8_thunder_map_event(struct perf_event *event) | ||
812 | { | ||
813 | return armpmu_map_event(event, &armv8_thunder_perf_map, | ||
814 | &armv8_thunder_perf_cache_map, | ||
815 | ARMV8_EVTYPE_EVENT); | ||
816 | } | ||
817 | |||
750 | static void armv8pmu_read_num_pmnc_events(void *info) | 818 | static void armv8pmu_read_num_pmnc_events(void *info) |
751 | { | 819 | { |
752 | int *nb_cnt = info; | 820 | int *nb_cnt = info; |
@@ -815,11 +883,21 @@ static int armv8_a72_pmu_init(struct arm_pmu *cpu_pmu) | |||
815 | return armv8pmu_probe_num_events(cpu_pmu); | 883 | return armv8pmu_probe_num_events(cpu_pmu); |
816 | } | 884 | } |
817 | 885 | ||
886 | static int armv8_thunder_pmu_init(struct arm_pmu *cpu_pmu) | ||
887 | { | ||
888 | armv8_pmu_init(cpu_pmu); | ||
889 | cpu_pmu->name = "armv8_cavium_thunder"; | ||
890 | cpu_pmu->map_event = armv8_thunder_map_event; | ||
891 | cpu_pmu->pmu.attr_groups = armv8_pmuv3_attr_groups; | ||
892 | return armv8pmu_probe_num_events(cpu_pmu); | ||
893 | } | ||
894 | |||
818 | static const struct of_device_id armv8_pmu_of_device_ids[] = { | 895 | static const struct of_device_id armv8_pmu_of_device_ids[] = { |
819 | {.compatible = "arm,armv8-pmuv3", .data = armv8_pmuv3_init}, | 896 | {.compatible = "arm,armv8-pmuv3", .data = armv8_pmuv3_init}, |
820 | {.compatible = "arm,cortex-a53-pmu", .data = armv8_a53_pmu_init}, | 897 | {.compatible = "arm,cortex-a53-pmu", .data = armv8_a53_pmu_init}, |
821 | {.compatible = "arm,cortex-a57-pmu", .data = armv8_a57_pmu_init}, | 898 | {.compatible = "arm,cortex-a57-pmu", .data = armv8_a57_pmu_init}, |
822 | {.compatible = "arm,cortex-a72-pmu", .data = armv8_a72_pmu_init}, | 899 | {.compatible = "arm,cortex-a72-pmu", .data = armv8_a72_pmu_init}, |
900 | {.compatible = "cavium,thunder-pmu", .data = armv8_thunder_pmu_init}, | ||
823 | {}, | 901 | {}, |
824 | }; | 902 | }; |
825 | 903 | ||
diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig index 9a92c072a485..d4a3a3133da5 100644 --- a/drivers/bus/Kconfig +++ b/drivers/bus/Kconfig | |||
@@ -34,15 +34,15 @@ config ARM_CCI400_PORT_CTRL | |||
34 | Low level power management driver for CCI400 cache coherent | 34 | Low level power management driver for CCI400 cache coherent |
35 | interconnect for ARM platforms. | 35 | interconnect for ARM platforms. |
36 | 36 | ||
37 | config ARM_CCI500_PMU | 37 | config ARM_CCI5xx_PMU |
38 | bool "ARM CCI500 PMU support" | 38 | bool "ARM CCI-500/CCI-550 PMU support" |
39 | depends on (ARM && CPU_V7) || ARM64 | 39 | depends on (ARM && CPU_V7) || ARM64 |
40 | depends on PERF_EVENTS | 40 | depends on PERF_EVENTS |
41 | select ARM_CCI_PMU | 41 | select ARM_CCI_PMU |
42 | help | 42 | help |
43 | Support for PMU events monitoring on the ARM CCI-500 cache coherent | 43 | Support for PMU events monitoring on the ARM CCI-500/CCI-550 cache |
44 | interconnect. CCI-500 provides 8 independent event counters, which | 44 | coherent interconnects. Both of them provide 8 independent event counters, |
45 | can count events pertaining to the slave/master interfaces as well | 45 | which can count events pertaining to the slave/master interfaces as well |
46 | as the internal events to the CCI. | 46 | as the internal events to the CCI. |
47 | 47 | ||
48 | If unsure, say Y | 48 | If unsure, say Y |
diff --git a/drivers/bus/arm-cci.c b/drivers/bus/arm-cci.c index 577cc4bf6a9d..a49b28378d59 100644 --- a/drivers/bus/arm-cci.c +++ b/drivers/bus/arm-cci.c | |||
@@ -52,8 +52,9 @@ static const struct of_device_id arm_cci_matches[] = { | |||
52 | #ifdef CONFIG_ARM_CCI400_COMMON | 52 | #ifdef CONFIG_ARM_CCI400_COMMON |
53 | {.compatible = "arm,cci-400", .data = CCI400_PORTS_DATA }, | 53 | {.compatible = "arm,cci-400", .data = CCI400_PORTS_DATA }, |
54 | #endif | 54 | #endif |
55 | #ifdef CONFIG_ARM_CCI500_PMU | 55 | #ifdef CONFIG_ARM_CCI5xx_PMU |
56 | { .compatible = "arm,cci-500", }, | 56 | { .compatible = "arm,cci-500", }, |
57 | { .compatible = "arm,cci-550", }, | ||
57 | #endif | 58 | #endif |
58 | {}, | 59 | {}, |
59 | }; | 60 | }; |
@@ -92,7 +93,7 @@ static const struct of_device_id arm_cci_matches[] = { | |||
92 | enum { | 93 | enum { |
93 | CCI_IF_SLAVE, | 94 | CCI_IF_SLAVE, |
94 | CCI_IF_MASTER, | 95 | CCI_IF_MASTER, |
95 | #ifdef CONFIG_ARM_CCI500_PMU | 96 | #ifdef CONFIG_ARM_CCI5xx_PMU |
96 | CCI_IF_GLOBAL, | 97 | CCI_IF_GLOBAL, |
97 | #endif | 98 | #endif |
98 | CCI_IF_MAX, | 99 | CCI_IF_MAX, |
@@ -121,13 +122,12 @@ struct cci_pmu_model { | |||
121 | u32 fixed_hw_cntrs; | 122 | u32 fixed_hw_cntrs; |
122 | u32 num_hw_cntrs; | 123 | u32 num_hw_cntrs; |
123 | u32 cntr_size; | 124 | u32 cntr_size; |
124 | u64 nformat_attrs; | 125 | struct attribute **format_attrs; |
125 | u64 nevent_attrs; | 126 | struct attribute **event_attrs; |
126 | struct dev_ext_attribute *format_attrs; | ||
127 | struct dev_ext_attribute *event_attrs; | ||
128 | struct event_range event_ranges[CCI_IF_MAX]; | 127 | struct event_range event_ranges[CCI_IF_MAX]; |
129 | int (*validate_hw_event)(struct cci_pmu *, unsigned long); | 128 | int (*validate_hw_event)(struct cci_pmu *, unsigned long); |
130 | int (*get_event_idx)(struct cci_pmu *, struct cci_pmu_hw_events *, unsigned long); | 129 | int (*get_event_idx)(struct cci_pmu *, struct cci_pmu_hw_events *, unsigned long); |
130 | void (*write_counters)(struct cci_pmu *, unsigned long *); | ||
131 | }; | 131 | }; |
132 | 132 | ||
133 | static struct cci_pmu_model cci_pmu_models[]; | 133 | static struct cci_pmu_model cci_pmu_models[]; |
@@ -155,19 +155,24 @@ enum cci_models { | |||
155 | CCI400_R0, | 155 | CCI400_R0, |
156 | CCI400_R1, | 156 | CCI400_R1, |
157 | #endif | 157 | #endif |
158 | #ifdef CONFIG_ARM_CCI500_PMU | 158 | #ifdef CONFIG_ARM_CCI5xx_PMU |
159 | CCI500_R0, | 159 | CCI500_R0, |
160 | CCI550_R0, | ||
160 | #endif | 161 | #endif |
161 | CCI_MODEL_MAX | 162 | CCI_MODEL_MAX |
162 | }; | 163 | }; |
163 | 164 | ||
165 | static void pmu_write_counters(struct cci_pmu *cci_pmu, | ||
166 | unsigned long *mask); | ||
164 | static ssize_t cci_pmu_format_show(struct device *dev, | 167 | static ssize_t cci_pmu_format_show(struct device *dev, |
165 | struct device_attribute *attr, char *buf); | 168 | struct device_attribute *attr, char *buf); |
166 | static ssize_t cci_pmu_event_show(struct device *dev, | 169 | static ssize_t cci_pmu_event_show(struct device *dev, |
167 | struct device_attribute *attr, char *buf); | 170 | struct device_attribute *attr, char *buf); |
168 | 171 | ||
169 | #define CCI_EXT_ATTR_ENTRY(_name, _func, _config) \ | 172 | #define CCI_EXT_ATTR_ENTRY(_name, _func, _config) \ |
170 | { __ATTR(_name, S_IRUGO, _func, NULL), (void *)_config } | 173 | &((struct dev_ext_attribute[]) { \ |
174 | { __ATTR(_name, S_IRUGO, _func, NULL), (void *)_config } \ | ||
175 | })[0].attr.attr | ||
171 | 176 | ||
172 | #define CCI_FORMAT_EXT_ATTR_ENTRY(_name, _config) \ | 177 | #define CCI_FORMAT_EXT_ATTR_ENTRY(_name, _config) \ |
173 | CCI_EXT_ATTR_ENTRY(_name, cci_pmu_format_show, (char *)_config) | 178 | CCI_EXT_ATTR_ENTRY(_name, cci_pmu_format_show, (char *)_config) |
@@ -242,12 +247,13 @@ enum cci400_perf_events { | |||
242 | static ssize_t cci400_pmu_cycle_event_show(struct device *dev, | 247 | static ssize_t cci400_pmu_cycle_event_show(struct device *dev, |
243 | struct device_attribute *attr, char *buf); | 248 | struct device_attribute *attr, char *buf); |
244 | 249 | ||
245 | static struct dev_ext_attribute cci400_pmu_format_attrs[] = { | 250 | static struct attribute *cci400_pmu_format_attrs[] = { |
246 | CCI_FORMAT_EXT_ATTR_ENTRY(event, "config:0-4"), | 251 | CCI_FORMAT_EXT_ATTR_ENTRY(event, "config:0-4"), |
247 | CCI_FORMAT_EXT_ATTR_ENTRY(source, "config:5-7"), | 252 | CCI_FORMAT_EXT_ATTR_ENTRY(source, "config:5-7"), |
253 | NULL | ||
248 | }; | 254 | }; |
249 | 255 | ||
250 | static struct dev_ext_attribute cci400_r0_pmu_event_attrs[] = { | 256 | static struct attribute *cci400_r0_pmu_event_attrs[] = { |
251 | /* Slave events */ | 257 | /* Slave events */ |
252 | CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_hs_any, 0x0), | 258 | CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_hs_any, 0x0), |
253 | CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_hs_device, 0x01), | 259 | CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_hs_device, 0x01), |
@@ -279,9 +285,10 @@ static struct dev_ext_attribute cci400_r0_pmu_event_attrs[] = { | |||
279 | CCI_EVENT_EXT_ATTR_ENTRY(mi_wrq_stall_tt_full, 0x1A), | 285 | CCI_EVENT_EXT_ATTR_ENTRY(mi_wrq_stall_tt_full, 0x1A), |
280 | /* Special event for cycles counter */ | 286 | /* Special event for cycles counter */ |
281 | CCI400_CYCLE_EVENT_EXT_ATTR_ENTRY(cycles, 0xff), | 287 | CCI400_CYCLE_EVENT_EXT_ATTR_ENTRY(cycles, 0xff), |
288 | NULL | ||
282 | }; | 289 | }; |
283 | 290 | ||
284 | static struct dev_ext_attribute cci400_r1_pmu_event_attrs[] = { | 291 | static struct attribute *cci400_r1_pmu_event_attrs[] = { |
285 | /* Slave events */ | 292 | /* Slave events */ |
286 | CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_hs_any, 0x0), | 293 | CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_hs_any, 0x0), |
287 | CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_hs_device, 0x01), | 294 | CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_hs_device, 0x01), |
@@ -325,6 +332,7 @@ static struct dev_ext_attribute cci400_r1_pmu_event_attrs[] = { | |||
325 | CCI_EVENT_EXT_ATTR_ENTRY(mi_wrq_unique_or_line_unique_addr_hazard, 0x11), | 332 | CCI_EVENT_EXT_ATTR_ENTRY(mi_wrq_unique_or_line_unique_addr_hazard, 0x11), |
326 | /* Special event for cycles counter */ | 333 | /* Special event for cycles counter */ |
327 | CCI400_CYCLE_EVENT_EXT_ATTR_ENTRY(cycles, 0xff), | 334 | CCI400_CYCLE_EVENT_EXT_ATTR_ENTRY(cycles, 0xff), |
335 | NULL | ||
328 | }; | 336 | }; |
329 | 337 | ||
330 | static ssize_t cci400_pmu_cycle_event_show(struct device *dev, | 338 | static ssize_t cci400_pmu_cycle_event_show(struct device *dev, |
@@ -420,72 +428,68 @@ static inline struct cci_pmu_model *probe_cci_model(struct platform_device *pdev | |||
420 | } | 428 | } |
421 | #endif /* CONFIG_ARM_CCI400_PMU */ | 429 | #endif /* CONFIG_ARM_CCI400_PMU */ |
422 | 430 | ||
423 | #ifdef CONFIG_ARM_CCI500_PMU | 431 | #ifdef CONFIG_ARM_CCI5xx_PMU |
424 | 432 | ||
425 | /* | 433 | /* |
426 | * CCI500 provides 8 independent event counters that can count | 434 | * CCI5xx PMU event id is an 9-bit value made of two parts. |
427 | * any of the events available. | ||
428 | * | ||
429 | * CCI500 PMU event id is an 9-bit value made of two parts. | ||
430 | * bits [8:5] - Source for the event | 435 | * bits [8:5] - Source for the event |
431 | * 0x0-0x6 - Slave interfaces | ||
432 | * 0x8-0xD - Master interfaces | ||
433 | * 0xf - Global Events | ||
434 | * 0x7,0xe - Reserved | ||
435 | * | ||
436 | * bits [4:0] - Event code (specific to type of interface) | 436 | * bits [4:0] - Event code (specific to type of interface) |
437 | * | ||
438 | * | ||
437 | */ | 439 | */ |
438 | 440 | ||
439 | /* Port ids */ | 441 | /* Port ids */ |
440 | #define CCI500_PORT_S0 0x0 | 442 | #define CCI5xx_PORT_S0 0x0 |
441 | #define CCI500_PORT_S1 0x1 | 443 | #define CCI5xx_PORT_S1 0x1 |
442 | #define CCI500_PORT_S2 0x2 | 444 | #define CCI5xx_PORT_S2 0x2 |
443 | #define CCI500_PORT_S3 0x3 | 445 | #define CCI5xx_PORT_S3 0x3 |
444 | #define CCI500_PORT_S4 0x4 | 446 | #define CCI5xx_PORT_S4 0x4 |
445 | #define CCI500_PORT_S5 0x5 | 447 | #define CCI5xx_PORT_S5 0x5 |
446 | #define CCI500_PORT_S6 0x6 | 448 | #define CCI5xx_PORT_S6 0x6 |
447 | 449 | ||
448 | #define CCI500_PORT_M0 0x8 | 450 | #define CCI5xx_PORT_M0 0x8 |
449 | #define CCI500_PORT_M1 0x9 | 451 | #define CCI5xx_PORT_M1 0x9 |
450 | #define CCI500_PORT_M2 0xa | 452 | #define CCI5xx_PORT_M2 0xa |
451 | #define CCI500_PORT_M3 0xb | 453 | #define CCI5xx_PORT_M3 0xb |
452 | #define CCI500_PORT_M4 0xc | 454 | #define CCI5xx_PORT_M4 0xc |
453 | #define CCI500_PORT_M5 0xd | 455 | #define CCI5xx_PORT_M5 0xd |
454 | 456 | #define CCI5xx_PORT_M6 0xe | |
455 | #define CCI500_PORT_GLOBAL 0xf | 457 | |
456 | 458 | #define CCI5xx_PORT_GLOBAL 0xf | |
457 | #define CCI500_PMU_EVENT_MASK 0x1ffUL | 459 | |
458 | #define CCI500_PMU_EVENT_SOURCE_SHIFT 0x5 | 460 | #define CCI5xx_PMU_EVENT_MASK 0x1ffUL |
459 | #define CCI500_PMU_EVENT_SOURCE_MASK 0xf | 461 | #define CCI5xx_PMU_EVENT_SOURCE_SHIFT 0x5 |
460 | #define CCI500_PMU_EVENT_CODE_SHIFT 0x0 | 462 | #define CCI5xx_PMU_EVENT_SOURCE_MASK 0xf |
461 | #define CCI500_PMU_EVENT_CODE_MASK 0x1f | 463 | #define CCI5xx_PMU_EVENT_CODE_SHIFT 0x0 |
462 | 464 | #define CCI5xx_PMU_EVENT_CODE_MASK 0x1f | |
463 | #define CCI500_PMU_EVENT_SOURCE(event) \ | 465 | |
464 | ((event >> CCI500_PMU_EVENT_SOURCE_SHIFT) & CCI500_PMU_EVENT_SOURCE_MASK) | 466 | #define CCI5xx_PMU_EVENT_SOURCE(event) \ |
465 | #define CCI500_PMU_EVENT_CODE(event) \ | 467 | ((event >> CCI5xx_PMU_EVENT_SOURCE_SHIFT) & CCI5xx_PMU_EVENT_SOURCE_MASK) |
466 | ((event >> CCI500_PMU_EVENT_CODE_SHIFT) & CCI500_PMU_EVENT_CODE_MASK) | 468 | #define CCI5xx_PMU_EVENT_CODE(event) \ |
467 | 469 | ((event >> CCI5xx_PMU_EVENT_CODE_SHIFT) & CCI5xx_PMU_EVENT_CODE_MASK) | |
468 | #define CCI500_SLAVE_PORT_MIN_EV 0x00 | 470 | |
469 | #define CCI500_SLAVE_PORT_MAX_EV 0x1f | 471 | #define CCI5xx_SLAVE_PORT_MIN_EV 0x00 |
470 | #define CCI500_MASTER_PORT_MIN_EV 0x00 | 472 | #define CCI5xx_SLAVE_PORT_MAX_EV 0x1f |
471 | #define CCI500_MASTER_PORT_MAX_EV 0x06 | 473 | #define CCI5xx_MASTER_PORT_MIN_EV 0x00 |
472 | #define CCI500_GLOBAL_PORT_MIN_EV 0x00 | 474 | #define CCI5xx_MASTER_PORT_MAX_EV 0x06 |
473 | #define CCI500_GLOBAL_PORT_MAX_EV 0x0f | 475 | #define CCI5xx_GLOBAL_PORT_MIN_EV 0x00 |
474 | 476 | #define CCI5xx_GLOBAL_PORT_MAX_EV 0x0f | |
475 | 477 | ||
476 | #define CCI500_GLOBAL_EVENT_EXT_ATTR_ENTRY(_name, _config) \ | 478 | |
477 | CCI_EXT_ATTR_ENTRY(_name, cci500_pmu_global_event_show, \ | 479 | #define CCI5xx_GLOBAL_EVENT_EXT_ATTR_ENTRY(_name, _config) \ |
480 | CCI_EXT_ATTR_ENTRY(_name, cci5xx_pmu_global_event_show, \ | ||
478 | (unsigned long) _config) | 481 | (unsigned long) _config) |
479 | 482 | ||
480 | static ssize_t cci500_pmu_global_event_show(struct device *dev, | 483 | static ssize_t cci5xx_pmu_global_event_show(struct device *dev, |
481 | struct device_attribute *attr, char *buf); | 484 | struct device_attribute *attr, char *buf); |
482 | 485 | ||
483 | static struct dev_ext_attribute cci500_pmu_format_attrs[] = { | 486 | static struct attribute *cci5xx_pmu_format_attrs[] = { |
484 | CCI_FORMAT_EXT_ATTR_ENTRY(event, "config:0-4"), | 487 | CCI_FORMAT_EXT_ATTR_ENTRY(event, "config:0-4"), |
485 | CCI_FORMAT_EXT_ATTR_ENTRY(source, "config:5-8"), | 488 | CCI_FORMAT_EXT_ATTR_ENTRY(source, "config:5-8"), |
489 | NULL, | ||
486 | }; | 490 | }; |
487 | 491 | ||
488 | static struct dev_ext_attribute cci500_pmu_event_attrs[] = { | 492 | static struct attribute *cci5xx_pmu_event_attrs[] = { |
489 | /* Slave events */ | 493 | /* Slave events */ |
490 | CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_hs_arvalid, 0x0), | 494 | CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_hs_arvalid, 0x0), |
491 | CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_dev, 0x1), | 495 | CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_dev, 0x1), |
@@ -530,63 +534,73 @@ static struct dev_ext_attribute cci500_pmu_event_attrs[] = { | |||
530 | CCI_EVENT_EXT_ATTR_ENTRY(mi_w_resp_stall, 0x6), | 534 | CCI_EVENT_EXT_ATTR_ENTRY(mi_w_resp_stall, 0x6), |
531 | 535 | ||
532 | /* Global events */ | 536 | /* Global events */ |
533 | CCI500_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_snoop_access_filter_bank_0_1, 0x0), | 537 | CCI5xx_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_snoop_access_filter_bank_0_1, 0x0), |
534 | CCI500_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_snoop_access_filter_bank_2_3, 0x1), | 538 | CCI5xx_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_snoop_access_filter_bank_2_3, 0x1), |
535 | CCI500_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_snoop_access_filter_bank_4_5, 0x2), | 539 | CCI5xx_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_snoop_access_filter_bank_4_5, 0x2), |
536 | CCI500_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_snoop_access_filter_bank_6_7, 0x3), | 540 | CCI5xx_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_snoop_access_filter_bank_6_7, 0x3), |
537 | CCI500_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_snoop_access_miss_filter_bank_0_1, 0x4), | 541 | CCI5xx_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_snoop_access_miss_filter_bank_0_1, 0x4), |
538 | CCI500_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_snoop_access_miss_filter_bank_2_3, 0x5), | 542 | CCI5xx_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_snoop_access_miss_filter_bank_2_3, 0x5), |
539 | CCI500_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_snoop_access_miss_filter_bank_4_5, 0x6), | 543 | CCI5xx_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_snoop_access_miss_filter_bank_4_5, 0x6), |
540 | CCI500_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_snoop_access_miss_filter_bank_6_7, 0x7), | 544 | CCI5xx_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_snoop_access_miss_filter_bank_6_7, 0x7), |
541 | CCI500_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_snoop_back_invalidation, 0x8), | 545 | CCI5xx_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_snoop_back_invalidation, 0x8), |
542 | CCI500_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_snoop_stall_alloc_busy, 0x9), | 546 | CCI5xx_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_snoop_stall_alloc_busy, 0x9), |
543 | CCI500_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_snoop_stall_tt_full, 0xA), | 547 | CCI5xx_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_snoop_stall_tt_full, 0xA), |
544 | CCI500_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_wrq, 0xB), | 548 | CCI5xx_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_wrq, 0xB), |
545 | CCI500_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_snoop_cd_hs, 0xC), | 549 | CCI5xx_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_snoop_cd_hs, 0xC), |
546 | CCI500_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_rq_stall_addr_hazard, 0xD), | 550 | CCI5xx_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_rq_stall_addr_hazard, 0xD), |
547 | CCI500_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_snopp_rq_stall_tt_full, 0xE), | 551 | CCI5xx_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_snopp_rq_stall_tt_full, 0xE), |
548 | CCI500_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_snoop_rq_tzmp1_prot, 0xF), | 552 | CCI5xx_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_snoop_rq_tzmp1_prot, 0xF), |
553 | NULL | ||
549 | }; | 554 | }; |
550 | 555 | ||
551 | static ssize_t cci500_pmu_global_event_show(struct device *dev, | 556 | static ssize_t cci5xx_pmu_global_event_show(struct device *dev, |
552 | struct device_attribute *attr, char *buf) | 557 | struct device_attribute *attr, char *buf) |
553 | { | 558 | { |
554 | struct dev_ext_attribute *eattr = container_of(attr, | 559 | struct dev_ext_attribute *eattr = container_of(attr, |
555 | struct dev_ext_attribute, attr); | 560 | struct dev_ext_attribute, attr); |
556 | /* Global events have single fixed source code */ | 561 | /* Global events have single fixed source code */ |
557 | return snprintf(buf, PAGE_SIZE, "event=0x%lx,source=0x%x\n", | 562 | return snprintf(buf, PAGE_SIZE, "event=0x%lx,source=0x%x\n", |
558 | (unsigned long)eattr->var, CCI500_PORT_GLOBAL); | 563 | (unsigned long)eattr->var, CCI5xx_PORT_GLOBAL); |
559 | } | 564 | } |
560 | 565 | ||
566 | /* | ||
567 | * CCI500 provides 8 independent event counters that can count | ||
568 | * any of the events available. | ||
569 | * CCI500 PMU event source ids | ||
570 | * 0x0-0x6 - Slave interfaces | ||
571 | * 0x8-0xD - Master interfaces | ||
572 | * 0xf - Global Events | ||
573 | * 0x7,0xe - Reserved | ||
574 | */ | ||
561 | static int cci500_validate_hw_event(struct cci_pmu *cci_pmu, | 575 | static int cci500_validate_hw_event(struct cci_pmu *cci_pmu, |
562 | unsigned long hw_event) | 576 | unsigned long hw_event) |
563 | { | 577 | { |
564 | u32 ev_source = CCI500_PMU_EVENT_SOURCE(hw_event); | 578 | u32 ev_source = CCI5xx_PMU_EVENT_SOURCE(hw_event); |
565 | u32 ev_code = CCI500_PMU_EVENT_CODE(hw_event); | 579 | u32 ev_code = CCI5xx_PMU_EVENT_CODE(hw_event); |
566 | int if_type; | 580 | int if_type; |
567 | 581 | ||
568 | if (hw_event & ~CCI500_PMU_EVENT_MASK) | 582 | if (hw_event & ~CCI5xx_PMU_EVENT_MASK) |
569 | return -ENOENT; | 583 | return -ENOENT; |
570 | 584 | ||
571 | switch (ev_source) { | 585 | switch (ev_source) { |
572 | case CCI500_PORT_S0: | 586 | case CCI5xx_PORT_S0: |
573 | case CCI500_PORT_S1: | 587 | case CCI5xx_PORT_S1: |
574 | case CCI500_PORT_S2: | 588 | case CCI5xx_PORT_S2: |
575 | case CCI500_PORT_S3: | 589 | case CCI5xx_PORT_S3: |
576 | case CCI500_PORT_S4: | 590 | case CCI5xx_PORT_S4: |
577 | case CCI500_PORT_S5: | 591 | case CCI5xx_PORT_S5: |
578 | case CCI500_PORT_S6: | 592 | case CCI5xx_PORT_S6: |
579 | if_type = CCI_IF_SLAVE; | 593 | if_type = CCI_IF_SLAVE; |
580 | break; | 594 | break; |
581 | case CCI500_PORT_M0: | 595 | case CCI5xx_PORT_M0: |
582 | case CCI500_PORT_M1: | 596 | case CCI5xx_PORT_M1: |
583 | case CCI500_PORT_M2: | 597 | case CCI5xx_PORT_M2: |
584 | case CCI500_PORT_M3: | 598 | case CCI5xx_PORT_M3: |
585 | case CCI500_PORT_M4: | 599 | case CCI5xx_PORT_M4: |
586 | case CCI500_PORT_M5: | 600 | case CCI5xx_PORT_M5: |
587 | if_type = CCI_IF_MASTER; | 601 | if_type = CCI_IF_MASTER; |
588 | break; | 602 | break; |
589 | case CCI500_PORT_GLOBAL: | 603 | case CCI5xx_PORT_GLOBAL: |
590 | if_type = CCI_IF_GLOBAL; | 604 | if_type = CCI_IF_GLOBAL; |
591 | break; | 605 | break; |
592 | default: | 606 | default: |
@@ -599,7 +613,118 @@ static int cci500_validate_hw_event(struct cci_pmu *cci_pmu, | |||
599 | 613 | ||
600 | return -ENOENT; | 614 | return -ENOENT; |
601 | } | 615 | } |
602 | #endif /* CONFIG_ARM_CCI500_PMU */ | 616 | |
617 | /* | ||
618 | * CCI550 provides 8 independent event counters that can count | ||
619 | * any of the events available. | ||
620 | * CCI550 PMU event source ids | ||
621 | * 0x0-0x6 - Slave interfaces | ||
622 | * 0x8-0xe - Master interfaces | ||
623 | * 0xf - Global Events | ||
624 | * 0x7 - Reserved | ||
625 | */ | ||
626 | static int cci550_validate_hw_event(struct cci_pmu *cci_pmu, | ||
627 | unsigned long hw_event) | ||
628 | { | ||
629 | u32 ev_source = CCI5xx_PMU_EVENT_SOURCE(hw_event); | ||
630 | u32 ev_code = CCI5xx_PMU_EVENT_CODE(hw_event); | ||
631 | int if_type; | ||
632 | |||
633 | if (hw_event & ~CCI5xx_PMU_EVENT_MASK) | ||
634 | return -ENOENT; | ||
635 | |||
636 | switch (ev_source) { | ||
637 | case CCI5xx_PORT_S0: | ||
638 | case CCI5xx_PORT_S1: | ||
639 | case CCI5xx_PORT_S2: | ||
640 | case CCI5xx_PORT_S3: | ||
641 | case CCI5xx_PORT_S4: | ||
642 | case CCI5xx_PORT_S5: | ||
643 | case CCI5xx_PORT_S6: | ||
644 | if_type = CCI_IF_SLAVE; | ||
645 | break; | ||
646 | case CCI5xx_PORT_M0: | ||
647 | case CCI5xx_PORT_M1: | ||
648 | case CCI5xx_PORT_M2: | ||
649 | case CCI5xx_PORT_M3: | ||
650 | case CCI5xx_PORT_M4: | ||
651 | case CCI5xx_PORT_M5: | ||
652 | case CCI5xx_PORT_M6: | ||
653 | if_type = CCI_IF_MASTER; | ||
654 | break; | ||
655 | case CCI5xx_PORT_GLOBAL: | ||
656 | if_type = CCI_IF_GLOBAL; | ||
657 | break; | ||
658 | default: | ||
659 | return -ENOENT; | ||
660 | } | ||
661 | |||
662 | if (ev_code >= cci_pmu->model->event_ranges[if_type].min && | ||
663 | ev_code <= cci_pmu->model->event_ranges[if_type].max) | ||
664 | return hw_event; | ||
665 | |||
666 | return -ENOENT; | ||
667 | } | ||
668 | |||
669 | #endif /* CONFIG_ARM_CCI5xx_PMU */ | ||
670 | |||
671 | /* | ||
672 | * Program the CCI PMU counters which have PERF_HES_ARCH set | ||
673 | * with the event period and mark them ready before we enable | ||
674 | * PMU. | ||
675 | */ | ||
676 | static void cci_pmu_sync_counters(struct cci_pmu *cci_pmu) | ||
677 | { | ||
678 | int i; | ||
679 | struct cci_pmu_hw_events *cci_hw = &cci_pmu->hw_events; | ||
680 | |||
681 | DECLARE_BITMAP(mask, cci_pmu->num_cntrs); | ||
682 | |||
683 | bitmap_zero(mask, cci_pmu->num_cntrs); | ||
684 | for_each_set_bit(i, cci_pmu->hw_events.used_mask, cci_pmu->num_cntrs) { | ||
685 | struct perf_event *event = cci_hw->events[i]; | ||
686 | |||
687 | if (WARN_ON(!event)) | ||
688 | continue; | ||
689 | |||
690 | /* Leave the events which are not counting */ | ||
691 | if (event->hw.state & PERF_HES_STOPPED) | ||
692 | continue; | ||
693 | if (event->hw.state & PERF_HES_ARCH) { | ||
694 | set_bit(i, mask); | ||
695 | event->hw.state &= ~PERF_HES_ARCH; | ||
696 | } | ||
697 | } | ||
698 | |||
699 | pmu_write_counters(cci_pmu, mask); | ||
700 | } | ||
701 | |||
702 | /* Should be called with cci_pmu->hw_events->pmu_lock held */ | ||
703 | static void __cci_pmu_enable_nosync(struct cci_pmu *cci_pmu) | ||
704 | { | ||
705 | u32 val; | ||
706 | |||
707 | /* Enable all the PMU counters. */ | ||
708 | val = readl_relaxed(cci_ctrl_base + CCI_PMCR) | CCI_PMCR_CEN; | ||
709 | writel(val, cci_ctrl_base + CCI_PMCR); | ||
710 | } | ||
711 | |||
712 | /* Should be called with cci_pmu->hw_events->pmu_lock held */ | ||
713 | static void __cci_pmu_enable_sync(struct cci_pmu *cci_pmu) | ||
714 | { | ||
715 | cci_pmu_sync_counters(cci_pmu); | ||
716 | __cci_pmu_enable_nosync(cci_pmu); | ||
717 | } | ||
718 | |||
719 | /* Should be called with cci_pmu->hw_events->pmu_lock held */ | ||
720 | static void __cci_pmu_disable(void) | ||
721 | { | ||
722 | u32 val; | ||
723 | |||
724 | /* Disable all the PMU counters. */ | ||
725 | val = readl_relaxed(cci_ctrl_base + CCI_PMCR) & ~CCI_PMCR_CEN; | ||
726 | writel(val, cci_ctrl_base + CCI_PMCR); | ||
727 | } | ||
603 | 728 | ||
604 | static ssize_t cci_pmu_format_show(struct device *dev, | 729 | static ssize_t cci_pmu_format_show(struct device *dev, |
605 | struct device_attribute *attr, char *buf) | 730 | struct device_attribute *attr, char *buf) |
@@ -633,8 +758,8 @@ static u32 pmu_read_register(struct cci_pmu *cci_pmu, int idx, unsigned int offs | |||
633 | static void pmu_write_register(struct cci_pmu *cci_pmu, u32 value, | 758 | static void pmu_write_register(struct cci_pmu *cci_pmu, u32 value, |
634 | int idx, unsigned int offset) | 759 | int idx, unsigned int offset) |
635 | { | 760 | { |
636 | return writel_relaxed(value, cci_pmu->base + | 761 | writel_relaxed(value, cci_pmu->base + |
637 | CCI_PMU_CNTR_BASE(cci_pmu->model, idx) + offset); | 762 | CCI_PMU_CNTR_BASE(cci_pmu->model, idx) + offset); |
638 | } | 763 | } |
639 | 764 | ||
640 | static void pmu_disable_counter(struct cci_pmu *cci_pmu, int idx) | 765 | static void pmu_disable_counter(struct cci_pmu *cci_pmu, int idx) |
@@ -647,12 +772,56 @@ static void pmu_enable_counter(struct cci_pmu *cci_pmu, int idx) | |||
647 | pmu_write_register(cci_pmu, 1, idx, CCI_PMU_CNTR_CTRL); | 772 | pmu_write_register(cci_pmu, 1, idx, CCI_PMU_CNTR_CTRL); |
648 | } | 773 | } |
649 | 774 | ||
775 | static bool __maybe_unused | ||
776 | pmu_counter_is_enabled(struct cci_pmu *cci_pmu, int idx) | ||
777 | { | ||
778 | return (pmu_read_register(cci_pmu, idx, CCI_PMU_CNTR_CTRL) & 0x1) != 0; | ||
779 | } | ||
780 | |||
650 | static void pmu_set_event(struct cci_pmu *cci_pmu, int idx, unsigned long event) | 781 | static void pmu_set_event(struct cci_pmu *cci_pmu, int idx, unsigned long event) |
651 | { | 782 | { |
652 | pmu_write_register(cci_pmu, event, idx, CCI_PMU_EVT_SEL); | 783 | pmu_write_register(cci_pmu, event, idx, CCI_PMU_EVT_SEL); |
653 | } | 784 | } |
654 | 785 | ||
655 | /* | 786 | /* |
787 | * For all counters on the CCI-PMU, disable any 'enabled' counters, | ||
788 | * saving the changed counters in the mask, so that we can restore | ||
789 | * it later using pmu_restore_counters. The mask is private to the | ||
790 | * caller. We cannot rely on the used_mask maintained by the CCI_PMU | ||
791 | * as it only tells us if the counter is assigned to perf_event or not. | ||
792 | * The state of the perf_event cannot be locked by the PMU layer, hence | ||
793 | * we check the individual counter status (which can be locked by | ||
794 | * cci_pm->hw_events->pmu_lock). | ||
795 | * | ||
796 | * @mask should be initialised to empty by the caller. | ||
797 | */ | ||
798 | static void __maybe_unused | ||
799 | pmu_save_counters(struct cci_pmu *cci_pmu, unsigned long *mask) | ||
800 | { | ||
801 | int i; | ||
802 | |||
803 | for (i = 0; i < cci_pmu->num_cntrs; i++) { | ||
804 | if (pmu_counter_is_enabled(cci_pmu, i)) { | ||
805 | set_bit(i, mask); | ||
806 | pmu_disable_counter(cci_pmu, i); | ||
807 | } | ||
808 | } | ||
809 | } | ||
810 | |||
811 | /* | ||
812 | * Restore the status of the counters. Reversal of the pmu_save_counters(). | ||
813 | * For each counter set in the mask, enable the counter back. | ||
814 | */ | ||
815 | static void __maybe_unused | ||
816 | pmu_restore_counters(struct cci_pmu *cci_pmu, unsigned long *mask) | ||
817 | { | ||
818 | int i; | ||
819 | |||
820 | for_each_set_bit(i, mask, cci_pmu->num_cntrs) | ||
821 | pmu_enable_counter(cci_pmu, i); | ||
822 | } | ||
823 | |||
824 | /* | ||
656 | * Returns the number of programmable counters actually implemented | 825 | * Returns the number of programmable counters actually implemented |
657 | * by the cci | 826 | * by the cci |
658 | */ | 827 | */ |
@@ -754,18 +923,98 @@ static u32 pmu_read_counter(struct perf_event *event) | |||
754 | return value; | 923 | return value; |
755 | } | 924 | } |
756 | 925 | ||
757 | static void pmu_write_counter(struct perf_event *event, u32 value) | 926 | static void pmu_write_counter(struct cci_pmu *cci_pmu, u32 value, int idx) |
758 | { | 927 | { |
759 | struct cci_pmu *cci_pmu = to_cci_pmu(event->pmu); | 928 | pmu_write_register(cci_pmu, value, idx, CCI_PMU_CNTR); |
760 | struct hw_perf_event *hw_counter = &event->hw; | 929 | } |
761 | int idx = hw_counter->idx; | ||
762 | 930 | ||
763 | if (unlikely(!pmu_is_valid_counter(cci_pmu, idx))) | 931 | static void __pmu_write_counters(struct cci_pmu *cci_pmu, unsigned long *mask) |
764 | dev_err(&cci_pmu->plat_device->dev, "Invalid CCI PMU counter %d\n", idx); | 932 | { |
933 | int i; | ||
934 | struct cci_pmu_hw_events *cci_hw = &cci_pmu->hw_events; | ||
935 | |||
936 | for_each_set_bit(i, mask, cci_pmu->num_cntrs) { | ||
937 | struct perf_event *event = cci_hw->events[i]; | ||
938 | |||
939 | if (WARN_ON(!event)) | ||
940 | continue; | ||
941 | pmu_write_counter(cci_pmu, local64_read(&event->hw.prev_count), i); | ||
942 | } | ||
943 | } | ||
944 | |||
945 | static void pmu_write_counters(struct cci_pmu *cci_pmu, unsigned long *mask) | ||
946 | { | ||
947 | if (cci_pmu->model->write_counters) | ||
948 | cci_pmu->model->write_counters(cci_pmu, mask); | ||
765 | else | 949 | else |
766 | pmu_write_register(cci_pmu, value, idx, CCI_PMU_CNTR); | 950 | __pmu_write_counters(cci_pmu, mask); |
767 | } | 951 | } |
768 | 952 | ||
953 | #ifdef CONFIG_ARM_CCI5xx_PMU | ||
954 | |||
955 | /* | ||
956 | * CCI-500/CCI-550 has advanced power saving policies, which could gate the | ||
957 | * clocks to the PMU counters, which makes the writes to them ineffective. | ||
958 | * The only way to write to those counters is when the global counters | ||
959 | * are enabled and the particular counter is enabled. | ||
960 | * | ||
961 | * So we do the following : | ||
962 | * | ||
963 | * 1) Disable all the PMU counters, saving their current state | ||
964 | * 2) Enable the global PMU profiling, now that all counters are | ||
965 | * disabled. | ||
966 | * | ||
967 | * For each counter to be programmed, repeat steps 3-7: | ||
968 | * | ||
969 | * 3) Write an invalid event code to the event control register for the | ||
970 | counter, so that the counters are not modified. | ||
971 | * 4) Enable the counter control for the counter. | ||
972 | * 5) Set the counter value | ||
973 | * 6) Disable the counter | ||
974 | * 7) Restore the event in the target counter | ||
975 | * | ||
976 | * 8) Disable the global PMU. | ||
977 | * 9) Restore the status of the rest of the counters. | ||
978 | * | ||
979 | * We choose an event which for CCI-5xx is guaranteed not to count. | ||
980 | * We use the highest possible event code (0x1f) for the master interface 0. | ||
981 | */ | ||
982 | #define CCI5xx_INVALID_EVENT ((CCI5xx_PORT_M0 << CCI5xx_PMU_EVENT_SOURCE_SHIFT) | \ | ||
983 | (CCI5xx_PMU_EVENT_CODE_MASK << CCI5xx_PMU_EVENT_CODE_SHIFT)) | ||
984 | static void cci5xx_pmu_write_counters(struct cci_pmu *cci_pmu, unsigned long *mask) | ||
985 | { | ||
986 | int i; | ||
987 | DECLARE_BITMAP(saved_mask, cci_pmu->num_cntrs); | ||
988 | |||
989 | bitmap_zero(saved_mask, cci_pmu->num_cntrs); | ||
990 | pmu_save_counters(cci_pmu, saved_mask); | ||
991 | |||
992 | /* | ||
993 | * Now that all the counters are disabled, we can safely turn the PMU on, | ||
994 | * without syncing the status of the counters | ||
995 | */ | ||
996 | __cci_pmu_enable_nosync(cci_pmu); | ||
997 | |||
998 | for_each_set_bit(i, mask, cci_pmu->num_cntrs) { | ||
999 | struct perf_event *event = cci_pmu->hw_events.events[i]; | ||
1000 | |||
1001 | if (WARN_ON(!event)) | ||
1002 | continue; | ||
1003 | |||
1004 | pmu_set_event(cci_pmu, i, CCI5xx_INVALID_EVENT); | ||
1005 | pmu_enable_counter(cci_pmu, i); | ||
1006 | pmu_write_counter(cci_pmu, local64_read(&event->hw.prev_count), i); | ||
1007 | pmu_disable_counter(cci_pmu, i); | ||
1008 | pmu_set_event(cci_pmu, i, event->hw.config_base); | ||
1009 | } | ||
1010 | |||
1011 | __cci_pmu_disable(); | ||
1012 | |||
1013 | pmu_restore_counters(cci_pmu, saved_mask); | ||
1014 | } | ||
1015 | |||
1016 | #endif /* CONFIG_ARM_CCI5xx_PMU */ | ||
1017 | |||
769 | static u64 pmu_event_update(struct perf_event *event) | 1018 | static u64 pmu_event_update(struct perf_event *event) |
770 | { | 1019 | { |
771 | struct hw_perf_event *hwc = &event->hw; | 1020 | struct hw_perf_event *hwc = &event->hw; |
@@ -789,7 +1038,7 @@ static void pmu_read(struct perf_event *event) | |||
789 | pmu_event_update(event); | 1038 | pmu_event_update(event); |
790 | } | 1039 | } |
791 | 1040 | ||
792 | void pmu_event_set_period(struct perf_event *event) | 1041 | static void pmu_event_set_period(struct perf_event *event) |
793 | { | 1042 | { |
794 | struct hw_perf_event *hwc = &event->hw; | 1043 | struct hw_perf_event *hwc = &event->hw; |
795 | /* | 1044 | /* |
@@ -800,7 +1049,14 @@ void pmu_event_set_period(struct perf_event *event) | |||
800 | */ | 1049 | */ |
801 | u64 val = 1ULL << 31; | 1050 | u64 val = 1ULL << 31; |
802 | local64_set(&hwc->prev_count, val); | 1051 | local64_set(&hwc->prev_count, val); |
803 | pmu_write_counter(event, val); | 1052 | |
1053 | /* | ||
1054 | * CCI PMU uses PERF_HES_ARCH to keep track of the counters, whose | ||
1055 | * values needs to be sync-ed with the s/w state before the PMU is | ||
1056 | * enabled. | ||
1057 | * Mark this counter for sync. | ||
1058 | */ | ||
1059 | hwc->state |= PERF_HES_ARCH; | ||
804 | } | 1060 | } |
805 | 1061 | ||
806 | static irqreturn_t pmu_handle_irq(int irq_num, void *dev) | 1062 | static irqreturn_t pmu_handle_irq(int irq_num, void *dev) |
@@ -811,6 +1067,9 @@ static irqreturn_t pmu_handle_irq(int irq_num, void *dev) | |||
811 | int idx, handled = IRQ_NONE; | 1067 | int idx, handled = IRQ_NONE; |
812 | 1068 | ||
813 | raw_spin_lock_irqsave(&events->pmu_lock, flags); | 1069 | raw_spin_lock_irqsave(&events->pmu_lock, flags); |
1070 | |||
1071 | /* Disable the PMU while we walk through the counters */ | ||
1072 | __cci_pmu_disable(); | ||
814 | /* | 1073 | /* |
815 | * Iterate over counters and update the corresponding perf events. | 1074 | * Iterate over counters and update the corresponding perf events. |
816 | * This should work regardless of whether we have per-counter overflow | 1075 | * This should work regardless of whether we have per-counter overflow |
@@ -818,13 +1077,10 @@ static irqreturn_t pmu_handle_irq(int irq_num, void *dev) | |||
818 | */ | 1077 | */ |
819 | for (idx = 0; idx <= CCI_PMU_CNTR_LAST(cci_pmu); idx++) { | 1078 | for (idx = 0; idx <= CCI_PMU_CNTR_LAST(cci_pmu); idx++) { |
820 | struct perf_event *event = events->events[idx]; | 1079 | struct perf_event *event = events->events[idx]; |
821 | struct hw_perf_event *hw_counter; | ||
822 | 1080 | ||
823 | if (!event) | 1081 | if (!event) |
824 | continue; | 1082 | continue; |
825 | 1083 | ||
826 | hw_counter = &event->hw; | ||
827 | |||
828 | /* Did this counter overflow? */ | 1084 | /* Did this counter overflow? */ |
829 | if (!(pmu_read_register(cci_pmu, idx, CCI_PMU_OVRFLW) & | 1085 | if (!(pmu_read_register(cci_pmu, idx, CCI_PMU_OVRFLW) & |
830 | CCI_PMU_OVRFLW_FLAG)) | 1086 | CCI_PMU_OVRFLW_FLAG)) |
@@ -837,6 +1093,9 @@ static irqreturn_t pmu_handle_irq(int irq_num, void *dev) | |||
837 | pmu_event_set_period(event); | 1093 | pmu_event_set_period(event); |
838 | handled = IRQ_HANDLED; | 1094 | handled = IRQ_HANDLED; |
839 | } | 1095 | } |
1096 | |||
1097 | /* Enable the PMU and sync possibly overflowed counters */ | ||
1098 | __cci_pmu_enable_sync(cci_pmu); | ||
840 | raw_spin_unlock_irqrestore(&events->pmu_lock, flags); | 1099 | raw_spin_unlock_irqrestore(&events->pmu_lock, flags); |
841 | 1100 | ||
842 | return IRQ_RETVAL(handled); | 1101 | return IRQ_RETVAL(handled); |
@@ -875,16 +1134,12 @@ static void cci_pmu_enable(struct pmu *pmu) | |||
875 | struct cci_pmu_hw_events *hw_events = &cci_pmu->hw_events; | 1134 | struct cci_pmu_hw_events *hw_events = &cci_pmu->hw_events; |
876 | int enabled = bitmap_weight(hw_events->used_mask, cci_pmu->num_cntrs); | 1135 | int enabled = bitmap_weight(hw_events->used_mask, cci_pmu->num_cntrs); |
877 | unsigned long flags; | 1136 | unsigned long flags; |
878 | u32 val; | ||
879 | 1137 | ||
880 | if (!enabled) | 1138 | if (!enabled) |
881 | return; | 1139 | return; |
882 | 1140 | ||
883 | raw_spin_lock_irqsave(&hw_events->pmu_lock, flags); | 1141 | raw_spin_lock_irqsave(&hw_events->pmu_lock, flags); |
884 | 1142 | __cci_pmu_enable_sync(cci_pmu); | |
885 | /* Enable all the PMU counters. */ | ||
886 | val = readl_relaxed(cci_ctrl_base + CCI_PMCR) | CCI_PMCR_CEN; | ||
887 | writel(val, cci_ctrl_base + CCI_PMCR); | ||
888 | raw_spin_unlock_irqrestore(&hw_events->pmu_lock, flags); | 1143 | raw_spin_unlock_irqrestore(&hw_events->pmu_lock, flags); |
889 | 1144 | ||
890 | } | 1145 | } |
@@ -894,13 +1149,9 @@ static void cci_pmu_disable(struct pmu *pmu) | |||
894 | struct cci_pmu *cci_pmu = to_cci_pmu(pmu); | 1149 | struct cci_pmu *cci_pmu = to_cci_pmu(pmu); |
895 | struct cci_pmu_hw_events *hw_events = &cci_pmu->hw_events; | 1150 | struct cci_pmu_hw_events *hw_events = &cci_pmu->hw_events; |
896 | unsigned long flags; | 1151 | unsigned long flags; |
897 | u32 val; | ||
898 | 1152 | ||
899 | raw_spin_lock_irqsave(&hw_events->pmu_lock, flags); | 1153 | raw_spin_lock_irqsave(&hw_events->pmu_lock, flags); |
900 | 1154 | __cci_pmu_disable(); | |
901 | /* Disable all the PMU counters. */ | ||
902 | val = readl_relaxed(cci_ctrl_base + CCI_PMCR) & ~CCI_PMCR_CEN; | ||
903 | writel(val, cci_ctrl_base + CCI_PMCR); | ||
904 | raw_spin_unlock_irqrestore(&hw_events->pmu_lock, flags); | 1155 | raw_spin_unlock_irqrestore(&hw_events->pmu_lock, flags); |
905 | } | 1156 | } |
906 | 1157 | ||
@@ -1176,9 +1427,8 @@ static int cci_pmu_event_init(struct perf_event *event) | |||
1176 | static ssize_t pmu_cpumask_attr_show(struct device *dev, | 1427 | static ssize_t pmu_cpumask_attr_show(struct device *dev, |
1177 | struct device_attribute *attr, char *buf) | 1428 | struct device_attribute *attr, char *buf) |
1178 | { | 1429 | { |
1179 | struct dev_ext_attribute *eattr = container_of(attr, | 1430 | struct pmu *pmu = dev_get_drvdata(dev); |
1180 | struct dev_ext_attribute, attr); | 1431 | struct cci_pmu *cci_pmu = to_cci_pmu(pmu); |
1181 | struct cci_pmu *cci_pmu = eattr->var; | ||
1182 | 1432 | ||
1183 | int n = scnprintf(buf, PAGE_SIZE - 1, "%*pbl", | 1433 | int n = scnprintf(buf, PAGE_SIZE - 1, "%*pbl", |
1184 | cpumask_pr_args(&cci_pmu->cpus)); | 1434 | cpumask_pr_args(&cci_pmu->cpus)); |
@@ -1187,13 +1437,11 @@ static ssize_t pmu_cpumask_attr_show(struct device *dev, | |||
1187 | return n; | 1437 | return n; |
1188 | } | 1438 | } |
1189 | 1439 | ||
1190 | static struct dev_ext_attribute pmu_cpumask_attr = { | 1440 | static struct device_attribute pmu_cpumask_attr = |
1191 | __ATTR(cpumask, S_IRUGO, pmu_cpumask_attr_show, NULL), | 1441 | __ATTR(cpumask, S_IRUGO, pmu_cpumask_attr_show, NULL); |
1192 | NULL, /* Populated in cci_pmu_init */ | ||
1193 | }; | ||
1194 | 1442 | ||
1195 | static struct attribute *pmu_attrs[] = { | 1443 | static struct attribute *pmu_attrs[] = { |
1196 | &pmu_cpumask_attr.attr.attr, | 1444 | &pmu_cpumask_attr.attr, |
1197 | NULL, | 1445 | NULL, |
1198 | }; | 1446 | }; |
1199 | 1447 | ||
@@ -1218,60 +1466,14 @@ static const struct attribute_group *pmu_attr_groups[] = { | |||
1218 | NULL | 1466 | NULL |
1219 | }; | 1467 | }; |
1220 | 1468 | ||
1221 | static struct attribute **alloc_attrs(struct platform_device *pdev, | ||
1222 | int n, struct dev_ext_attribute *source) | ||
1223 | { | ||
1224 | int i; | ||
1225 | struct attribute **attrs; | ||
1226 | |||
1227 | /* Alloc n + 1 (for terminating NULL) */ | ||
1228 | attrs = devm_kcalloc(&pdev->dev, n + 1, sizeof(struct attribute *), | ||
1229 | GFP_KERNEL); | ||
1230 | if (!attrs) | ||
1231 | return attrs; | ||
1232 | for(i = 0; i < n; i++) | ||
1233 | attrs[i] = &source[i].attr.attr; | ||
1234 | return attrs; | ||
1235 | } | ||
1236 | |||
1237 | static int cci_pmu_init_attrs(struct cci_pmu *cci_pmu, struct platform_device *pdev) | ||
1238 | { | ||
1239 | const struct cci_pmu_model *model = cci_pmu->model; | ||
1240 | struct attribute **attrs; | ||
1241 | |||
1242 | /* | ||
1243 | * All allocations below are managed, hence doesn't need to be | ||
1244 | * free'd explicitly in case of an error. | ||
1245 | */ | ||
1246 | |||
1247 | if (model->nevent_attrs) { | ||
1248 | attrs = alloc_attrs(pdev, model->nevent_attrs, | ||
1249 | model->event_attrs); | ||
1250 | if (!attrs) | ||
1251 | return -ENOMEM; | ||
1252 | pmu_event_attr_group.attrs = attrs; | ||
1253 | } | ||
1254 | if (model->nformat_attrs) { | ||
1255 | attrs = alloc_attrs(pdev, model->nformat_attrs, | ||
1256 | model->format_attrs); | ||
1257 | if (!attrs) | ||
1258 | return -ENOMEM; | ||
1259 | pmu_format_attr_group.attrs = attrs; | ||
1260 | } | ||
1261 | pmu_cpumask_attr.var = cci_pmu; | ||
1262 | |||
1263 | return 0; | ||
1264 | } | ||
1265 | |||
1266 | static int cci_pmu_init(struct cci_pmu *cci_pmu, struct platform_device *pdev) | 1469 | static int cci_pmu_init(struct cci_pmu *cci_pmu, struct platform_device *pdev) |
1267 | { | 1470 | { |
1268 | char *name = cci_pmu->model->name; | 1471 | const struct cci_pmu_model *model = cci_pmu->model; |
1472 | char *name = model->name; | ||
1269 | u32 num_cntrs; | 1473 | u32 num_cntrs; |
1270 | int rc; | ||
1271 | 1474 | ||
1272 | rc = cci_pmu_init_attrs(cci_pmu, pdev); | 1475 | pmu_event_attr_group.attrs = model->event_attrs; |
1273 | if (rc) | 1476 | pmu_format_attr_group.attrs = model->format_attrs; |
1274 | return rc; | ||
1275 | 1477 | ||
1276 | cci_pmu->pmu = (struct pmu) { | 1478 | cci_pmu->pmu = (struct pmu) { |
1277 | .name = cci_pmu->model->name, | 1479 | .name = cci_pmu->model->name, |
@@ -1314,7 +1516,7 @@ static int cci_pmu_cpu_notifier(struct notifier_block *self, | |||
1314 | if (!cpumask_test_and_clear_cpu(cpu, &cci_pmu->cpus)) | 1516 | if (!cpumask_test_and_clear_cpu(cpu, &cci_pmu->cpus)) |
1315 | break; | 1517 | break; |
1316 | target = cpumask_any_but(cpu_online_mask, cpu); | 1518 | target = cpumask_any_but(cpu_online_mask, cpu); |
1317 | if (target < 0) // UP, last CPU | 1519 | if (target >= nr_cpu_ids) // UP, last CPU |
1318 | break; | 1520 | break; |
1319 | /* | 1521 | /* |
1320 | * TODO: migrate context once core races on event->ctx have | 1522 | * TODO: migrate context once core races on event->ctx have |
@@ -1336,9 +1538,7 @@ static struct cci_pmu_model cci_pmu_models[] = { | |||
1336 | .num_hw_cntrs = 4, | 1538 | .num_hw_cntrs = 4, |
1337 | .cntr_size = SZ_4K, | 1539 | .cntr_size = SZ_4K, |
1338 | .format_attrs = cci400_pmu_format_attrs, | 1540 | .format_attrs = cci400_pmu_format_attrs, |
1339 | .nformat_attrs = ARRAY_SIZE(cci400_pmu_format_attrs), | ||
1340 | .event_attrs = cci400_r0_pmu_event_attrs, | 1541 | .event_attrs = cci400_r0_pmu_event_attrs, |
1341 | .nevent_attrs = ARRAY_SIZE(cci400_r0_pmu_event_attrs), | ||
1342 | .event_ranges = { | 1542 | .event_ranges = { |
1343 | [CCI_IF_SLAVE] = { | 1543 | [CCI_IF_SLAVE] = { |
1344 | CCI400_R0_SLAVE_PORT_MIN_EV, | 1544 | CCI400_R0_SLAVE_PORT_MIN_EV, |
@@ -1358,9 +1558,7 @@ static struct cci_pmu_model cci_pmu_models[] = { | |||
1358 | .num_hw_cntrs = 4, | 1558 | .num_hw_cntrs = 4, |
1359 | .cntr_size = SZ_4K, | 1559 | .cntr_size = SZ_4K, |
1360 | .format_attrs = cci400_pmu_format_attrs, | 1560 | .format_attrs = cci400_pmu_format_attrs, |
1361 | .nformat_attrs = ARRAY_SIZE(cci400_pmu_format_attrs), | ||
1362 | .event_attrs = cci400_r1_pmu_event_attrs, | 1561 | .event_attrs = cci400_r1_pmu_event_attrs, |
1363 | .nevent_attrs = ARRAY_SIZE(cci400_r1_pmu_event_attrs), | ||
1364 | .event_ranges = { | 1562 | .event_ranges = { |
1365 | [CCI_IF_SLAVE] = { | 1563 | [CCI_IF_SLAVE] = { |
1366 | CCI400_R1_SLAVE_PORT_MIN_EV, | 1564 | CCI400_R1_SLAVE_PORT_MIN_EV, |
@@ -1375,31 +1573,54 @@ static struct cci_pmu_model cci_pmu_models[] = { | |||
1375 | .get_event_idx = cci400_get_event_idx, | 1573 | .get_event_idx = cci400_get_event_idx, |
1376 | }, | 1574 | }, |
1377 | #endif | 1575 | #endif |
1378 | #ifdef CONFIG_ARM_CCI500_PMU | 1576 | #ifdef CONFIG_ARM_CCI5xx_PMU |
1379 | [CCI500_R0] = { | 1577 | [CCI500_R0] = { |
1380 | .name = "CCI_500", | 1578 | .name = "CCI_500", |
1381 | .fixed_hw_cntrs = 0, | 1579 | .fixed_hw_cntrs = 0, |
1382 | .num_hw_cntrs = 8, | 1580 | .num_hw_cntrs = 8, |
1383 | .cntr_size = SZ_64K, | 1581 | .cntr_size = SZ_64K, |
1384 | .format_attrs = cci500_pmu_format_attrs, | 1582 | .format_attrs = cci5xx_pmu_format_attrs, |
1385 | .nformat_attrs = ARRAY_SIZE(cci500_pmu_format_attrs), | 1583 | .event_attrs = cci5xx_pmu_event_attrs, |
1386 | .event_attrs = cci500_pmu_event_attrs, | ||
1387 | .nevent_attrs = ARRAY_SIZE(cci500_pmu_event_attrs), | ||
1388 | .event_ranges = { | 1584 | .event_ranges = { |
1389 | [CCI_IF_SLAVE] = { | 1585 | [CCI_IF_SLAVE] = { |
1390 | CCI500_SLAVE_PORT_MIN_EV, | 1586 | CCI5xx_SLAVE_PORT_MIN_EV, |
1391 | CCI500_SLAVE_PORT_MAX_EV, | 1587 | CCI5xx_SLAVE_PORT_MAX_EV, |
1392 | }, | 1588 | }, |
1393 | [CCI_IF_MASTER] = { | 1589 | [CCI_IF_MASTER] = { |
1394 | CCI500_MASTER_PORT_MIN_EV, | 1590 | CCI5xx_MASTER_PORT_MIN_EV, |
1395 | CCI500_MASTER_PORT_MAX_EV, | 1591 | CCI5xx_MASTER_PORT_MAX_EV, |
1396 | }, | 1592 | }, |
1397 | [CCI_IF_GLOBAL] = { | 1593 | [CCI_IF_GLOBAL] = { |
1398 | CCI500_GLOBAL_PORT_MIN_EV, | 1594 | CCI5xx_GLOBAL_PORT_MIN_EV, |
1399 | CCI500_GLOBAL_PORT_MAX_EV, | 1595 | CCI5xx_GLOBAL_PORT_MAX_EV, |
1400 | }, | 1596 | }, |
1401 | }, | 1597 | }, |
1402 | .validate_hw_event = cci500_validate_hw_event, | 1598 | .validate_hw_event = cci500_validate_hw_event, |
1599 | .write_counters = cci5xx_pmu_write_counters, | ||
1600 | }, | ||
1601 | [CCI550_R0] = { | ||
1602 | .name = "CCI_550", | ||
1603 | .fixed_hw_cntrs = 0, | ||
1604 | .num_hw_cntrs = 8, | ||
1605 | .cntr_size = SZ_64K, | ||
1606 | .format_attrs = cci5xx_pmu_format_attrs, | ||
1607 | .event_attrs = cci5xx_pmu_event_attrs, | ||
1608 | .event_ranges = { | ||
1609 | [CCI_IF_SLAVE] = { | ||
1610 | CCI5xx_SLAVE_PORT_MIN_EV, | ||
1611 | CCI5xx_SLAVE_PORT_MAX_EV, | ||
1612 | }, | ||
1613 | [CCI_IF_MASTER] = { | ||
1614 | CCI5xx_MASTER_PORT_MIN_EV, | ||
1615 | CCI5xx_MASTER_PORT_MAX_EV, | ||
1616 | }, | ||
1617 | [CCI_IF_GLOBAL] = { | ||
1618 | CCI5xx_GLOBAL_PORT_MIN_EV, | ||
1619 | CCI5xx_GLOBAL_PORT_MAX_EV, | ||
1620 | }, | ||
1621 | }, | ||
1622 | .validate_hw_event = cci550_validate_hw_event, | ||
1623 | .write_counters = cci5xx_pmu_write_counters, | ||
1403 | }, | 1624 | }, |
1404 | #endif | 1625 | #endif |
1405 | }; | 1626 | }; |
@@ -1419,11 +1640,15 @@ static const struct of_device_id arm_cci_pmu_matches[] = { | |||
1419 | .data = &cci_pmu_models[CCI400_R1], | 1640 | .data = &cci_pmu_models[CCI400_R1], |
1420 | }, | 1641 | }, |
1421 | #endif | 1642 | #endif |
1422 | #ifdef CONFIG_ARM_CCI500_PMU | 1643 | #ifdef CONFIG_ARM_CCI5xx_PMU |
1423 | { | 1644 | { |
1424 | .compatible = "arm,cci-500-pmu,r0", | 1645 | .compatible = "arm,cci-500-pmu,r0", |
1425 | .data = &cci_pmu_models[CCI500_R0], | 1646 | .data = &cci_pmu_models[CCI500_R0], |
1426 | }, | 1647 | }, |
1648 | { | ||
1649 | .compatible = "arm,cci-550-pmu,r0", | ||
1650 | .data = &cci_pmu_models[CCI550_R0], | ||
1651 | }, | ||
1427 | #endif | 1652 | #endif |
1428 | {}, | 1653 | {}, |
1429 | }; | 1654 | }; |
diff --git a/drivers/perf/arm_pmu.c b/drivers/perf/arm_pmu.c index 166637f2917c..32346b5a8a11 100644 --- a/drivers/perf/arm_pmu.c +++ b/drivers/perf/arm_pmu.c | |||
@@ -13,6 +13,7 @@ | |||
13 | 13 | ||
14 | #include <linux/bitmap.h> | 14 | #include <linux/bitmap.h> |
15 | #include <linux/cpumask.h> | 15 | #include <linux/cpumask.h> |
16 | #include <linux/cpu_pm.h> | ||
16 | #include <linux/export.h> | 17 | #include <linux/export.h> |
17 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
18 | #include <linux/of_device.h> | 19 | #include <linux/of_device.h> |
@@ -710,6 +711,93 @@ static int cpu_pmu_notify(struct notifier_block *b, unsigned long action, | |||
710 | return NOTIFY_OK; | 711 | return NOTIFY_OK; |
711 | } | 712 | } |
712 | 713 | ||
714 | #ifdef CONFIG_CPU_PM | ||
715 | static void cpu_pm_pmu_setup(struct arm_pmu *armpmu, unsigned long cmd) | ||
716 | { | ||
717 | struct pmu_hw_events *hw_events = this_cpu_ptr(armpmu->hw_events); | ||
718 | struct perf_event *event; | ||
719 | int idx; | ||
720 | |||
721 | for (idx = 0; idx < armpmu->num_events; idx++) { | ||
722 | /* | ||
723 | * If the counter is not used skip it, there is no | ||
724 | * need of stopping/restarting it. | ||
725 | */ | ||
726 | if (!test_bit(idx, hw_events->used_mask)) | ||
727 | continue; | ||
728 | |||
729 | event = hw_events->events[idx]; | ||
730 | |||
731 | switch (cmd) { | ||
732 | case CPU_PM_ENTER: | ||
733 | /* | ||
734 | * Stop and update the counter | ||
735 | */ | ||
736 | armpmu_stop(event, PERF_EF_UPDATE); | ||
737 | break; | ||
738 | case CPU_PM_EXIT: | ||
739 | case CPU_PM_ENTER_FAILED: | ||
740 | /* Restore and enable the counter */ | ||
741 | armpmu_start(event, PERF_EF_RELOAD); | ||
742 | break; | ||
743 | default: | ||
744 | break; | ||
745 | } | ||
746 | } | ||
747 | } | ||
748 | |||
749 | static int cpu_pm_pmu_notify(struct notifier_block *b, unsigned long cmd, | ||
750 | void *v) | ||
751 | { | ||
752 | struct arm_pmu *armpmu = container_of(b, struct arm_pmu, cpu_pm_nb); | ||
753 | struct pmu_hw_events *hw_events = this_cpu_ptr(armpmu->hw_events); | ||
754 | int enabled = bitmap_weight(hw_events->used_mask, armpmu->num_events); | ||
755 | |||
756 | if (!cpumask_test_cpu(smp_processor_id(), &armpmu->supported_cpus)) | ||
757 | return NOTIFY_DONE; | ||
758 | |||
759 | /* | ||
760 | * Always reset the PMU registers on power-up even if | ||
761 | * there are no events running. | ||
762 | */ | ||
763 | if (cmd == CPU_PM_EXIT && armpmu->reset) | ||
764 | armpmu->reset(armpmu); | ||
765 | |||
766 | if (!enabled) | ||
767 | return NOTIFY_OK; | ||
768 | |||
769 | switch (cmd) { | ||
770 | case CPU_PM_ENTER: | ||
771 | armpmu->stop(armpmu); | ||
772 | cpu_pm_pmu_setup(armpmu, cmd); | ||
773 | break; | ||
774 | case CPU_PM_EXIT: | ||
775 | cpu_pm_pmu_setup(armpmu, cmd); | ||
776 | case CPU_PM_ENTER_FAILED: | ||
777 | armpmu->start(armpmu); | ||
778 | break; | ||
779 | default: | ||
780 | return NOTIFY_DONE; | ||
781 | } | ||
782 | |||
783 | return NOTIFY_OK; | ||
784 | } | ||
785 | |||
786 | static int cpu_pm_pmu_register(struct arm_pmu *cpu_pmu) | ||
787 | { | ||
788 | cpu_pmu->cpu_pm_nb.notifier_call = cpu_pm_pmu_notify; | ||
789 | return cpu_pm_register_notifier(&cpu_pmu->cpu_pm_nb); | ||
790 | } | ||
791 | |||
792 | static void cpu_pm_pmu_unregister(struct arm_pmu *cpu_pmu) | ||
793 | { | ||
794 | cpu_pm_unregister_notifier(&cpu_pmu->cpu_pm_nb); | ||
795 | } | ||
796 | #else | ||
797 | static inline int cpu_pm_pmu_register(struct arm_pmu *cpu_pmu) { return 0; } | ||
798 | static inline void cpu_pm_pmu_unregister(struct arm_pmu *cpu_pmu) { } | ||
799 | #endif | ||
800 | |||
713 | static int cpu_pmu_init(struct arm_pmu *cpu_pmu) | 801 | static int cpu_pmu_init(struct arm_pmu *cpu_pmu) |
714 | { | 802 | { |
715 | int err; | 803 | int err; |
@@ -725,6 +813,10 @@ static int cpu_pmu_init(struct arm_pmu *cpu_pmu) | |||
725 | if (err) | 813 | if (err) |
726 | goto out_hw_events; | 814 | goto out_hw_events; |
727 | 815 | ||
816 | err = cpu_pm_pmu_register(cpu_pmu); | ||
817 | if (err) | ||
818 | goto out_unregister; | ||
819 | |||
728 | for_each_possible_cpu(cpu) { | 820 | for_each_possible_cpu(cpu) { |
729 | struct pmu_hw_events *events = per_cpu_ptr(cpu_hw_events, cpu); | 821 | struct pmu_hw_events *events = per_cpu_ptr(cpu_hw_events, cpu); |
730 | raw_spin_lock_init(&events->pmu_lock); | 822 | raw_spin_lock_init(&events->pmu_lock); |
@@ -746,6 +838,8 @@ static int cpu_pmu_init(struct arm_pmu *cpu_pmu) | |||
746 | 838 | ||
747 | return 0; | 839 | return 0; |
748 | 840 | ||
841 | out_unregister: | ||
842 | unregister_cpu_notifier(&cpu_pmu->hotplug_nb); | ||
749 | out_hw_events: | 843 | out_hw_events: |
750 | free_percpu(cpu_hw_events); | 844 | free_percpu(cpu_hw_events); |
751 | return err; | 845 | return err; |
@@ -753,6 +847,7 @@ out_hw_events: | |||
753 | 847 | ||
754 | static void cpu_pmu_destroy(struct arm_pmu *cpu_pmu) | 848 | static void cpu_pmu_destroy(struct arm_pmu *cpu_pmu) |
755 | { | 849 | { |
850 | cpu_pm_pmu_unregister(cpu_pmu); | ||
756 | unregister_cpu_notifier(&cpu_pmu->hotplug_nb); | 851 | unregister_cpu_notifier(&cpu_pmu->hotplug_nb); |
757 | free_percpu(cpu_pmu->hw_events); | 852 | free_percpu(cpu_pmu->hw_events); |
758 | } | 853 | } |
@@ -889,6 +984,15 @@ int arm_pmu_device_probe(struct platform_device *pdev, | |||
889 | if (node && (of_id = of_match_node(of_table, pdev->dev.of_node))) { | 984 | if (node && (of_id = of_match_node(of_table, pdev->dev.of_node))) { |
890 | init_fn = of_id->data; | 985 | init_fn = of_id->data; |
891 | 986 | ||
987 | pmu->secure_access = of_property_read_bool(pdev->dev.of_node, | ||
988 | "secure-reg-access"); | ||
989 | |||
990 | /* arm64 systems boot only as non-secure */ | ||
991 | if (IS_ENABLED(CONFIG_ARM64) && pmu->secure_access) { | ||
992 | pr_warn("ignoring \"secure-reg-access\" property for arm64\n"); | ||
993 | pmu->secure_access = false; | ||
994 | } | ||
995 | |||
892 | ret = of_pmu_irq_cfg(pmu); | 996 | ret = of_pmu_irq_cfg(pmu); |
893 | if (!ret) | 997 | if (!ret) |
894 | ret = init_fn(pmu); | 998 | ret = init_fn(pmu); |
@@ -898,7 +1002,7 @@ int arm_pmu_device_probe(struct platform_device *pdev, | |||
898 | } | 1002 | } |
899 | 1003 | ||
900 | if (ret) { | 1004 | if (ret) { |
901 | pr_info("failed to probe PMU!\n"); | 1005 | pr_info("%s: failed to probe PMU!\n", of_node_full_name(node)); |
902 | goto out_free; | 1006 | goto out_free; |
903 | } | 1007 | } |
904 | 1008 | ||
@@ -918,7 +1022,8 @@ int arm_pmu_device_probe(struct platform_device *pdev, | |||
918 | out_destroy: | 1022 | out_destroy: |
919 | cpu_pmu_destroy(pmu); | 1023 | cpu_pmu_destroy(pmu); |
920 | out_free: | 1024 | out_free: |
921 | pr_info("failed to register PMU devices!\n"); | 1025 | pr_info("%s: failed to register PMU devices!\n", |
1026 | of_node_full_name(node)); | ||
922 | kfree(pmu); | 1027 | kfree(pmu); |
923 | return ret; | 1028 | return ret; |
924 | } | 1029 | } |
diff --git a/include/linux/perf/arm_pmu.h b/include/linux/perf/arm_pmu.h index 83b5e34c6580..4196c90a3c88 100644 --- a/include/linux/perf/arm_pmu.h +++ b/include/linux/perf/arm_pmu.h | |||
@@ -104,9 +104,11 @@ struct arm_pmu { | |||
104 | atomic_t active_events; | 104 | atomic_t active_events; |
105 | struct mutex reserve_mutex; | 105 | struct mutex reserve_mutex; |
106 | u64 max_period; | 106 | u64 max_period; |
107 | bool secure_access; /* 32-bit ARM only */ | ||
107 | struct platform_device *plat_device; | 108 | struct platform_device *plat_device; |
108 | struct pmu_hw_events __percpu *hw_events; | 109 | struct pmu_hw_events __percpu *hw_events; |
109 | struct notifier_block hotplug_nb; | 110 | struct notifier_block hotplug_nb; |
111 | struct notifier_block cpu_pm_nb; | ||
110 | }; | 112 | }; |
111 | 113 | ||
112 | #define to_arm_pmu(p) (container_of(p, struct arm_pmu, pmu)) | 114 | #define to_arm_pmu(p) (container_of(p, struct arm_pmu, pmu)) |