History

Merge branch 'for-next/perf' into for-next/core

* for-next/perf: (25 commits) perf/marvell: Fix !CONFIG_OF build for CN10K DDR PMU driver drivers/perf: Add Apple icestorm/firestorm CPU PMU driver drivers/perf: arm_pmu: Handle 47 bit counters arm64: perf: Consistently make all event numbers as 16-bits arm64: perf: Expose some Armv9 common events under sysfs perf/marvell: cn10k DDR perf event core ownership perf/marvell: cn10k DDR perfmon event overflow handling perf/marvell: CN10k DDR performance monitor support dt-bindings: perf: marvell: cn10k ddr performance monitor perf/arm-cmn: Update watchpoint format perf/arm-cmn: Hide XP PUB events for CMN-600 perf: replace bitmap_weight with bitmap_empty where appropriate perf: Replace acpi_bus_get_device() perf/marvell_cn10k: Fix unused variable warning when W=1 and CONFIG_OF=n perf/arm-cmn: Make arm_cmn_debugfs static perf: MARVELL_CN10K_TAD_PMU should depend on ARCH_THUNDER perf/arm-ccn: Use platform_get_irq() to get the interrupt irqchip/apple-aic: Move PMU-specific registers to their own include file arm64: dts: apple: Add t8303 PMU nodes arm64: dts: apple: Add t8103 PMU interrupt affinities ...

Will Deacon committed 4 years ago

Commit b5ef94f2 parents 292ca2d 6676a4223 files · +1800 −198Browse files

Unified · Split

23 files
  1. Documentation/devicetree/bindings/arm/pmu.yaml +2 −0
  2. Documentation/devicetree/bindings/interrupt-controller/apple,aic.yaml +31 −0
  3. Documentation/devicetree/bindings/perf/marvell-cn10k-ddr.yaml +37 −0
  4. arch/arm64/boot/dts/apple/t8103.dtsi +24 −0
  5. arch/arm64/include/asm/apple_m1_pmu.h +64 −0
  6. arch/arm64/include/asm/perf_event.h +163 −149
  7. arch/arm64/kernel/perf_event.c +10 −0
  8. drivers/irqchip/irq-apple-aic.c +72 −22
  9. drivers/perf/Kconfig +15 −1
  10. drivers/perf/Makefile +2 −0
  11. drivers/perf/apple_m1_cpu_pmu.c +584 −0
  12. drivers/perf/arm-cci.c +1 −1
  13. drivers/perf/arm-ccn.c +4 −6
  14. drivers/perf/arm-cmn.c +16 −7
  15. drivers/perf/arm_pmu.c +4 −2
  16. drivers/perf/hisilicon/hisi_uncore_pmu.c +1 −1
  17. drivers/perf/marvell_cn10k_ddr_pmu.c +758 −0
  18. drivers/perf/marvell_cn10k_tad_pmu.c +2 −0
  19. drivers/perf/thunderx2_pmu.c +2 −4
  20. drivers/perf/xgene_pmu.c +3 −5
  21. include/dt-bindings/interrupt-controller/apple-aic.h +2 −0
  22. include/linux/cpuhotplug.h +1 −0
  23. include/linux/perf/arm_pmu.h +2 −0
Documentation/devicetree/bindings/arm/pmu.yaml+2−0
@@ -20,6 +20,8 @@ properties: · 19 unmodified lines
2020 items:
2121 - enum:
2222 - apm,potenza-pmu
23+ - apple,firestorm-pmu
24+ - apple,icestorm-pmu
2325 - arm,armv8-pmuv3 # Only for s/w models
2426 - arm,arm1136-pmu
2527 - arm,arm1176-pmu
Documentation/devicetree/bindings/interrupt-controller/apple,aic.yaml+31−0
@@ -56,6 +56,8 @@ properties: · 55 unmodified lines
5656 - 1: virtual HV timer
5757 - 2: physical guest timer
5858 - 3: virtual guest timer
59+ - 4: 'efficient' CPU PMU
60+ - 5: 'performance' CPU PMU
5961
6062 The 3rd cell contains the interrupt flags. This is normally
6163 IRQ_TYPE_LEVEL_HIGH (4).
@@ -68,6 +70,35 @@ properties: · 6 unmodified lines
6870 power-domains:
6971 maxItems: 1
7072
73+ affinities:
74+ type: object
75+ additionalProperties: false
76+ description:
77+ FIQ affinity can be expressed as a single "affinities" node,
78+ containing a set of sub-nodes, one per FIQ with a non-default
79+ affinity.
80+ patternProperties:
81+ "^.+-affinity$":
82+ type: object
83+ additionalProperties: false
84+ properties:
85+ apple,fiq-index:
86+ description:
87+ The interrupt number specified as a FIQ, and for which
88+ the affinity is not the default.
89+ $ref: /schemas/types.yaml#/definitions/uint32
90+ maximum: 5
91+
92+ cpus:
93+ $ref: /schemas/types.yaml#/definitions/phandle-array
94+ description:
95+ Should be a list of phandles to CPU nodes (as described in
96+ Documentation/devicetree/bindings/arm/cpus.yaml).
97+
98+ required:
99+ - fiq-index
100+ - cpus
101+
71102 required:
72103 - compatible
73104 - '#interrupt-cells'
Documentation/devicetree/bindings/perf/marvell-cn10k-ddr.yaml+37−0
@@ -0,0 +1,37 @@
1+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2+%YAML 1.2
3+---
4+$id: http://devicetree.org/schemas/perf/marvell-cn10k-ddr.yaml#
5+$schema: http://devicetree.org/meta-schemas/core.yaml#
6+
7+title: Marvell CN10K DDR performance monitor
8+
9+maintainers:
10+ - Bharat Bhushan <bbhushan2@marvell.com>
11+
12+properties:
13+ compatible:
14+ items:
15+ - enum:
16+ - marvell,cn10k-ddr-pmu
17+
18+ reg:
19+ maxItems: 1
20+
21+required:
22+ - compatible
23+ - reg
24+
25+additionalProperties: false
26+
27+examples:
28+ - |
29+ bus {
30+ #address-cells = <2>;
31+ #size-cells = <2>;
32+
33+ pmu@87e1c0000000 {
34+ compatible = "marvell,cn10k-ddr-pmu";
35+ reg = <0x87e1 0xc0000000 0x0 0x10000>;
36+ };
37+ };
arch/arm64/boot/dts/apple/t8103.dtsi+24−0
@@ -97,6 +97,18 @@ · 96 unmodified lines
9797 <AIC_FIQ AIC_TMR_HV_VIRT IRQ_TYPE_LEVEL_HIGH>;
9898 };
9999
100+ pmu-e {
101+ compatible = "apple,icestorm-pmu";
102+ interrupt-parent = <&aic>;
103+ interrupts = <AIC_FIQ AIC_CPU_PMU_E IRQ_TYPE_LEVEL_HIGH>;
104+ };
105+
106+ pmu-p {
107+ compatible = "apple,firestorm-pmu";
108+ interrupt-parent = <&aic>;
109+ interrupts = <AIC_FIQ AIC_CPU_PMU_P IRQ_TYPE_LEVEL_HIGH>;
110+ };
111+
100112 clkref: clock-ref {
101113 compatible = "fixed-clock";
102114 #clock-cells = <0>;
@@ -213,6 +225,18 @@ · 110 unmodified lines
213225 interrupt-controller;
214226 reg = <0x2 0x3b100000 0x0 0x8000>;
215227 power-domains = <&ps_aic>;
228+
229+ affinities {
230+ e-core-pmu-affinity {
231+ apple,fiq-index = <AIC_CPU_PMU_E>;
232+ cpus = <&cpu0 &cpu1 &cpu2 &cpu3>;
233+ };
234+
235+ p-core-pmu-affinity {
236+ apple,fiq-index = <AIC_CPU_PMU_P>;
237+ cpus = <&cpu4 &cpu5 &cpu6 &cpu7>;
238+ };
239+ };
216240 };
217241
218242 pmgr: power-management@23b700000 {
arch/arm64/include/asm/apple_m1_pmu.h+64−0
@@ -0,0 +1,64 @@
1+// SPDX-License-Identifier: GPL-2.0
2+
3+#ifndef __ASM_APPLE_M1_PMU_h
4+#define __ASM_APPLE_M1_PMU_h
5+
6+#include <linux/bits.h>
7+#include <asm/sysreg.h>
8+
9+/* Counters */
10+#define SYS_IMP_APL_PMC0_EL1 sys_reg(3, 2, 15, 0, 0)
11+#define SYS_IMP_APL_PMC1_EL1 sys_reg(3, 2, 15, 1, 0)
12+#define SYS_IMP_APL_PMC2_EL1 sys_reg(3, 2, 15, 2, 0)
13+#define SYS_IMP_APL_PMC3_EL1 sys_reg(3, 2, 15, 3, 0)
14+#define SYS_IMP_APL_PMC4_EL1 sys_reg(3, 2, 15, 4, 0)
15+#define SYS_IMP_APL_PMC5_EL1 sys_reg(3, 2, 15, 5, 0)
16+#define SYS_IMP_APL_PMC6_EL1 sys_reg(3, 2, 15, 6, 0)
17+#define SYS_IMP_APL_PMC7_EL1 sys_reg(3, 2, 15, 7, 0)
18+#define SYS_IMP_APL_PMC8_EL1 sys_reg(3, 2, 15, 9, 0)
19+#define SYS_IMP_APL_PMC9_EL1 sys_reg(3, 2, 15, 10, 0)
20+
21+/* Core PMC control register */
22+#define SYS_IMP_APL_PMCR0_EL1 sys_reg(3, 1, 15, 0, 0)
23+#define PMCR0_CNT_ENABLE_0_7 GENMASK(7, 0)
24+#define PMCR0_IMODE GENMASK(10, 8)
25+#define PMCR0_IMODE_OFF 0
26+#define PMCR0_IMODE_PMI 1
27+#define PMCR0_IMODE_AIC 2
28+#define PMCR0_IMODE_HALT 3
29+#define PMCR0_IMODE_FIQ 4
30+#define PMCR0_IACT BIT(11)
31+#define PMCR0_PMI_ENABLE_0_7 GENMASK(19, 12)
32+#define PMCR0_STOP_CNT_ON_PMI BIT(20)
33+#define PMCR0_CNT_GLOB_L2C_EVT BIT(21)
34+#define PMCR0_DEFER_PMI_TO_ERET BIT(22)
35+#define PMCR0_ALLOW_CNT_EN_EL0 BIT(30)
36+#define PMCR0_CNT_ENABLE_8_9 GENMASK(33, 32)
37+#define PMCR0_PMI_ENABLE_8_9 GENMASK(45, 44)
38+
39+#define SYS_IMP_APL_PMCR1_EL1 sys_reg(3, 1, 15, 1, 0)
40+#define PMCR1_COUNT_A64_EL0_0_7 GENMASK(15, 8)
41+#define PMCR1_COUNT_A64_EL1_0_7 GENMASK(23, 16)
42+#define PMCR1_COUNT_A64_EL0_8_9 GENMASK(41, 40)
43+#define PMCR1_COUNT_A64_EL1_8_9 GENMASK(49, 48)
44+
45+#define SYS_IMP_APL_PMCR2_EL1 sys_reg(3, 1, 15, 2, 0)
46+#define SYS_IMP_APL_PMCR3_EL1 sys_reg(3, 1, 15, 3, 0)
47+#define SYS_IMP_APL_PMCR4_EL1 sys_reg(3, 1, 15, 4, 0)
48+
49+#define SYS_IMP_APL_PMESR0_EL1 sys_reg(3, 1, 15, 5, 0)
50+#define PMESR0_EVT_CNT_2 GENMASK(7, 0)
51+#define PMESR0_EVT_CNT_3 GENMASK(15, 8)
52+#define PMESR0_EVT_CNT_4 GENMASK(23, 16)
53+#define PMESR0_EVT_CNT_5 GENMASK(31, 24)
54+
55+#define SYS_IMP_APL_PMESR1_EL1 sys_reg(3, 1, 15, 6, 0)
56+#define PMESR1_EVT_CNT_6 GENMASK(7, 0)
57+#define PMESR1_EVT_CNT_7 GENMASK(15, 8)
58+#define PMESR1_EVT_CNT_8 GENMASK(23, 16)
59+#define PMESR1_EVT_CNT_9 GENMASK(31, 24)
60+
61+#define SYS_IMP_APL_PMSR_EL1 sys_reg(3, 1, 15, 13, 0)
62+#define PMSR_OVERFLOW GENMASK(9, 0)
63+
64+#endif /* __ASM_APPLE_M1_PMU_h */
arch/arm64/include/asm/perf_event.h+163−149
@@ -15,70 +15,70 @@ · 14 unmodified lines
1515 /*
1616 * Common architectural and microarchitectural event numbers.
1717 */
18−#define ARMV8_PMUV3_PERFCTR_SW_INCR 0x00
19−#define ARMV8_PMUV3_PERFCTR_L1I_CACHE_REFILL 0x01
20−#define ARMV8_PMUV3_PERFCTR_L1I_TLB_REFILL 0x02
21−#define ARMV8_PMUV3_PERFCTR_L1D_CACHE_REFILL 0x03
22−#define ARMV8_PMUV3_PERFCTR_L1D_CACHE 0x04
23−#define ARMV8_PMUV3_PERFCTR_L1D_TLB_REFILL 0x05
24−#define ARMV8_PMUV3_PERFCTR_LD_RETIRED 0x06
25−#define ARMV8_PMUV3_PERFCTR_ST_RETIRED 0x07
26−#define ARMV8_PMUV3_PERFCTR_INST_RETIRED 0x08
27−#define ARMV8_PMUV3_PERFCTR_EXC_TAKEN 0x09
28−#define ARMV8_PMUV3_PERFCTR_EXC_RETURN 0x0A
29−#define ARMV8_PMUV3_PERFCTR_CID_WRITE_RETIRED 0x0B
30−#define ARMV8_PMUV3_PERFCTR_PC_WRITE_RETIRED 0x0C
31−#define ARMV8_PMUV3_PERFCTR_BR_IMMED_RETIRED 0x0D
32−#define ARMV8_PMUV3_PERFCTR_BR_RETURN_RETIRED 0x0E
33−#define ARMV8_PMUV3_PERFCTR_UNALIGNED_LDST_RETIRED 0x0F
34−#define ARMV8_PMUV3_PERFCTR_BR_MIS_PRED 0x10
35−#define ARMV8_PMUV3_PERFCTR_CPU_CYCLES 0x11
36−#define ARMV8_PMUV3_PERFCTR_BR_PRED 0x12
37−#define ARMV8_PMUV3_PERFCTR_MEM_ACCESS 0x13
38−#define ARMV8_PMUV3_PERFCTR_L1I_CACHE 0x14
39−#define ARMV8_PMUV3_PERFCTR_L1D_CACHE_WB 0x15
40−#define ARMV8_PMUV3_PERFCTR_L2D_CACHE 0x16
41−#define ARMV8_PMUV3_PERFCTR_L2D_CACHE_REFILL 0x17
42−#define ARMV8_PMUV3_PERFCTR_L2D_CACHE_WB 0x18
43−#define ARMV8_PMUV3_PERFCTR_BUS_ACCESS 0x19
44−#define ARMV8_PMUV3_PERFCTR_MEMORY_ERROR 0x1A
45−#define ARMV8_PMUV3_PERFCTR_INST_SPEC 0x1B
46−#define ARMV8_PMUV3_PERFCTR_TTBR_WRITE_RETIRED 0x1C
47−#define ARMV8_PMUV3_PERFCTR_BUS_CYCLES 0x1D
48−#define ARMV8_PMUV3_PERFCTR_CHAIN 0x1E
49−#define ARMV8_PMUV3_PERFCTR_L1D_CACHE_ALLOCATE 0x1F
50−#define ARMV8_PMUV3_PERFCTR_L2D_CACHE_ALLOCATE 0x20
51−#define ARMV8_PMUV3_PERFCTR_BR_RETIRED 0x21
52−#define ARMV8_PMUV3_PERFCTR_BR_MIS_PRED_RETIRED 0x22
53−#define ARMV8_PMUV3_PERFCTR_STALL_FRONTEND 0x23
54−#define ARMV8_PMUV3_PERFCTR_STALL_BACKEND 0x24
55−#define ARMV8_PMUV3_PERFCTR_L1D_TLB 0x25
56−#define ARMV8_PMUV3_PERFCTR_L1I_TLB 0x26
57−#define ARMV8_PMUV3_PERFCTR_L2I_CACHE 0x27
58−#define ARMV8_PMUV3_PERFCTR_L2I_CACHE_REFILL 0x28
59−#define ARMV8_PMUV3_PERFCTR_L3D_CACHE_ALLOCATE 0x29
60−#define ARMV8_PMUV3_PERFCTR_L3D_CACHE_REFILL 0x2A
61−#define ARMV8_PMUV3_PERFCTR_L3D_CACHE 0x2B
62−#define ARMV8_PMUV3_PERFCTR_L3D_CACHE_WB 0x2C
63−#define ARMV8_PMUV3_PERFCTR_L2D_TLB_REFILL 0x2D
64−#define ARMV8_PMUV3_PERFCTR_L2I_TLB_REFILL 0x2E
65−#define ARMV8_PMUV3_PERFCTR_L2D_TLB 0x2F
66−#define ARMV8_PMUV3_PERFCTR_L2I_TLB 0x30
67−#define ARMV8_PMUV3_PERFCTR_REMOTE_ACCESS 0x31
68−#define ARMV8_PMUV3_PERFCTR_LL_CACHE 0x32
69−#define ARMV8_PMUV3_PERFCTR_LL_CACHE_MISS 0x33
70−#define ARMV8_PMUV3_PERFCTR_DTLB_WALK 0x34
71−#define ARMV8_PMUV3_PERFCTR_ITLB_WALK 0x35
72−#define ARMV8_PMUV3_PERFCTR_LL_CACHE_RD 0x36
73−#define ARMV8_PMUV3_PERFCTR_LL_CACHE_MISS_RD 0x37
74−#define ARMV8_PMUV3_PERFCTR_REMOTE_ACCESS_RD 0x38
75−#define ARMV8_PMUV3_PERFCTR_L1D_CACHE_LMISS_RD 0x39
76−#define ARMV8_PMUV3_PERFCTR_OP_RETIRED 0x3A
77−#define ARMV8_PMUV3_PERFCTR_OP_SPEC 0x3B
78−#define ARMV8_PMUV3_PERFCTR_STALL 0x3C
79−#define ARMV8_PMUV3_PERFCTR_STALL_SLOT_BACKEND 0x3D
80−#define ARMV8_PMUV3_PERFCTR_STALL_SLOT_FRONTEND 0x3E
81−#define ARMV8_PMUV3_PERFCTR_STALL_SLOT 0x3F
18+#define ARMV8_PMUV3_PERFCTR_SW_INCR 0x0000
19+#define ARMV8_PMUV3_PERFCTR_L1I_CACHE_REFILL 0x0001
20+#define ARMV8_PMUV3_PERFCTR_L1I_TLB_REFILL 0x0002
21+#define ARMV8_PMUV3_PERFCTR_L1D_CACHE_REFILL 0x0003
22+#define ARMV8_PMUV3_PERFCTR_L1D_CACHE 0x0004
23+#define ARMV8_PMUV3_PERFCTR_L1D_TLB_REFILL 0x0005
24+#define ARMV8_PMUV3_PERFCTR_LD_RETIRED 0x0006
25+#define ARMV8_PMUV3_PERFCTR_ST_RETIRED 0x0007
26+#define ARMV8_PMUV3_PERFCTR_INST_RETIRED 0x0008
27+#define ARMV8_PMUV3_PERFCTR_EXC_TAKEN 0x0009
28+#define ARMV8_PMUV3_PERFCTR_EXC_RETURN 0x000A
29+#define ARMV8_PMUV3_PERFCTR_CID_WRITE_RETIRED 0x000B
30+#define ARMV8_PMUV3_PERFCTR_PC_WRITE_RETIRED 0x000C
31+#define ARMV8_PMUV3_PERFCTR_BR_IMMED_RETIRED 0x000D
32+#define ARMV8_PMUV3_PERFCTR_BR_RETURN_RETIRED 0x000E
33+#define ARMV8_PMUV3_PERFCTR_UNALIGNED_LDST_RETIRED 0x000F
34+#define ARMV8_PMUV3_PERFCTR_BR_MIS_PRED 0x0010
35+#define ARMV8_PMUV3_PERFCTR_CPU_CYCLES 0x0011
36+#define ARMV8_PMUV3_PERFCTR_BR_PRED 0x0012
37+#define ARMV8_PMUV3_PERFCTR_MEM_ACCESS 0x0013
38+#define ARMV8_PMUV3_PERFCTR_L1I_CACHE 0x0014
39+#define ARMV8_PMUV3_PERFCTR_L1D_CACHE_WB 0x0015
40+#define ARMV8_PMUV3_PERFCTR_L2D_CACHE 0x0016
41+#define ARMV8_PMUV3_PERFCTR_L2D_CACHE_REFILL 0x0017
42+#define ARMV8_PMUV3_PERFCTR_L2D_CACHE_WB 0x0018
43+#define ARMV8_PMUV3_PERFCTR_BUS_ACCESS 0x0019
44+#define ARMV8_PMUV3_PERFCTR_MEMORY_ERROR 0x001A
45+#define ARMV8_PMUV3_PERFCTR_INST_SPEC 0x001B
46+#define ARMV8_PMUV3_PERFCTR_TTBR_WRITE_RETIRED 0x001C
47+#define ARMV8_PMUV3_PERFCTR_BUS_CYCLES 0x001D
48+#define ARMV8_PMUV3_PERFCTR_CHAIN 0x001E
49+#define ARMV8_PMUV3_PERFCTR_L1D_CACHE_ALLOCATE 0x001F
50+#define ARMV8_PMUV3_PERFCTR_L2D_CACHE_ALLOCATE 0x0020
51+#define ARMV8_PMUV3_PERFCTR_BR_RETIRED 0x0021
52+#define ARMV8_PMUV3_PERFCTR_BR_MIS_PRED_RETIRED 0x0022
53+#define ARMV8_PMUV3_PERFCTR_STALL_FRONTEND 0x0023
54+#define ARMV8_PMUV3_PERFCTR_STALL_BACKEND 0x0024
55+#define ARMV8_PMUV3_PERFCTR_L1D_TLB 0x0025
56+#define ARMV8_PMUV3_PERFCTR_L1I_TLB 0x0026
57+#define ARMV8_PMUV3_PERFCTR_L2I_CACHE 0x0027
58+#define ARMV8_PMUV3_PERFCTR_L2I_CACHE_REFILL 0x0028
59+#define ARMV8_PMUV3_PERFCTR_L3D_CACHE_ALLOCATE 0x0029
60+#define ARMV8_PMUV3_PERFCTR_L3D_CACHE_REFILL 0x002A
61+#define ARMV8_PMUV3_PERFCTR_L3D_CACHE 0x002B
62+#define ARMV8_PMUV3_PERFCTR_L3D_CACHE_WB 0x002C
63+#define ARMV8_PMUV3_PERFCTR_L2D_TLB_REFILL 0x002D
64+#define ARMV8_PMUV3_PERFCTR_L2I_TLB_REFILL 0x002E
65+#define ARMV8_PMUV3_PERFCTR_L2D_TLB 0x002F
66+#define ARMV8_PMUV3_PERFCTR_L2I_TLB 0x0030
67+#define ARMV8_PMUV3_PERFCTR_REMOTE_ACCESS 0x0031
68+#define ARMV8_PMUV3_PERFCTR_LL_CACHE 0x0032
69+#define ARMV8_PMUV3_PERFCTR_LL_CACHE_MISS 0x0033
70+#define ARMV8_PMUV3_PERFCTR_DTLB_WALK 0x0034
71+#define ARMV8_PMUV3_PERFCTR_ITLB_WALK 0x0035
72+#define ARMV8_PMUV3_PERFCTR_LL_CACHE_RD 0x0036
73+#define ARMV8_PMUV3_PERFCTR_LL_CACHE_MISS_RD 0x0037
74+#define ARMV8_PMUV3_PERFCTR_REMOTE_ACCESS_RD 0x0038
75+#define ARMV8_PMUV3_PERFCTR_L1D_CACHE_LMISS_RD 0x0039
76+#define ARMV8_PMUV3_PERFCTR_OP_RETIRED 0x003A
77+#define ARMV8_PMUV3_PERFCTR_OP_SPEC 0x003B
78+#define ARMV8_PMUV3_PERFCTR_STALL 0x003C
79+#define ARMV8_PMUV3_PERFCTR_STALL_SLOT_BACKEND 0x003D
80+#define ARMV8_PMUV3_PERFCTR_STALL_SLOT_FRONTEND 0x003E
81+#define ARMV8_PMUV3_PERFCTR_STALL_SLOT 0x003F
8282
8383 /* Statistical profiling extension microarchitectural events */
8484 #define ARMV8_SPE_PERFCTR_SAMPLE_POP 0x4000
@@ -96,6 +96,20 @@ · 11 unmodified lines
9696 #define ARMV8_PMUV3_PERFCTR_L2I_CACHE_LMISS 0x400A
9797 #define ARMV8_PMUV3_PERFCTR_L3D_CACHE_LMISS_RD 0x400B
9898
99+/* Trace buffer events */
100+#define ARMV8_PMUV3_PERFCTR_TRB_WRAP 0x400C
101+#define ARMV8_PMUV3_PERFCTR_TRB_TRIG 0x400E
102+
103+/* Trace unit events */
104+#define ARMV8_PMUV3_PERFCTR_TRCEXTOUT0 0x4010
105+#define ARMV8_PMUV3_PERFCTR_TRCEXTOUT1 0x4011
106+#define ARMV8_PMUV3_PERFCTR_TRCEXTOUT2 0x4012
107+#define ARMV8_PMUV3_PERFCTR_TRCEXTOUT3 0x4013
108+#define ARMV8_PMUV3_PERFCTR_CTI_TRIGOUT4 0x4018
109+#define ARMV8_PMUV3_PERFCTR_CTI_TRIGOUT5 0x4019
110+#define ARMV8_PMUV3_PERFCTR_CTI_TRIGOUT6 0x401A
111+#define ARMV8_PMUV3_PERFCTR_CTI_TRIGOUT7 0x401B
112+
99113 /* additional latency from alignment events */
100114 #define ARMV8_PMUV3_PERFCTR_LDST_ALIGN_LAT 0x4020
101115 #define ARMV8_PMUV3_PERFCTR_LD_ALIGN_LAT 0x4021
@@ -107,91 +121,91 @@ · 5 unmodified lines
107121 #define ARMV8_MTE_PERFCTR_MEM_ACCESS_CHECKED_WR 0x4026
108122
109123 /* ARMv8 recommended implementation defined event types */
110−#define ARMV8_IMPDEF_PERFCTR_L1D_CACHE_RD 0x40
111−#define ARMV8_IMPDEF_PERFCTR_L1D_CACHE_WR 0x41
112−#define ARMV8_IMPDEF_PERFCTR_L1D_CACHE_REFILL_RD 0x42
113−#define ARMV8_IMPDEF_PERFCTR_L1D_CACHE_REFILL_WR 0x43
114−#define ARMV8_IMPDEF_PERFCTR_L1D_CACHE_REFILL_INNER 0x44
115−#define ARMV8_IMPDEF_PERFCTR_L1D_CACHE_REFILL_OUTER 0x45
116−#define ARMV8_IMPDEF_PERFCTR_L1D_CACHE_WB_VICTIM 0x46
117−#define ARMV8_IMPDEF_PERFCTR_L1D_CACHE_WB_CLEAN 0x47
118−#define ARMV8_IMPDEF_PERFCTR_L1D_CACHE_INVAL 0x48
119−
120−#define ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_RD 0x4C
121−#define ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_WR 0x4D
122−#define ARMV8_IMPDEF_PERFCTR_L1D_TLB_RD 0x4E
123−#define ARMV8_IMPDEF_PERFCTR_L1D_TLB_WR 0x4F
124−#define ARMV8_IMPDEF_PERFCTR_L2D_CACHE_RD 0x50
125−#define ARMV8_IMPDEF_PERFCTR_L2D_CACHE_WR 0x51
126−#define ARMV8_IMPDEF_PERFCTR_L2D_CACHE_REFILL_RD 0x52
127−#define ARMV8_IMPDEF_PERFCTR_L2D_CACHE_REFILL_WR 0x53
128−
129−#define ARMV8_IMPDEF_PERFCTR_L2D_CACHE_WB_VICTIM 0x56
130−#define ARMV8_IMPDEF_PERFCTR_L2D_CACHE_WB_CLEAN 0x57
131−#define ARMV8_IMPDEF_PERFCTR_L2D_CACHE_INVAL 0x58
132−
133−#define ARMV8_IMPDEF_PERFCTR_L2D_TLB_REFILL_RD 0x5C
134−#define ARMV8_IMPDEF_PERFCTR_L2D_TLB_REFILL_WR 0x5D
135−#define ARMV8_IMPDEF_PERFCTR_L2D_TLB_RD 0x5E
136−#define ARMV8_IMPDEF_PERFCTR_L2D_TLB_WR 0x5F
137−#define ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_RD 0x60
138−#define ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_WR 0x61
139−#define ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_SHARED 0x62
140−#define ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_NOT_SHARED 0x63
141−#define ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_NORMAL 0x64
142−#define ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_PERIPH 0x65
143−#define ARMV8_IMPDEF_PERFCTR_MEM_ACCESS_RD 0x66
144−#define ARMV8_IMPDEF_PERFCTR_MEM_ACCESS_WR 0x67
145−#define ARMV8_IMPDEF_PERFCTR_UNALIGNED_LD_SPEC 0x68
146−#define ARMV8_IMPDEF_PERFCTR_UNALIGNED_ST_SPEC 0x69
147−#define ARMV8_IMPDEF_PERFCTR_UNALIGNED_LDST_SPEC 0x6A
148−
149−#define ARMV8_IMPDEF_PERFCTR_LDREX_SPEC 0x6C
150−#define ARMV8_IMPDEF_PERFCTR_STREX_PASS_SPEC 0x6D
151−#define ARMV8_IMPDEF_PERFCTR_STREX_FAIL_SPEC 0x6E
152−#define ARMV8_IMPDEF_PERFCTR_STREX_SPEC 0x6F
153−#define ARMV8_IMPDEF_PERFCTR_LD_SPEC 0x70
154−#define ARMV8_IMPDEF_PERFCTR_ST_SPEC 0x71
155−#define ARMV8_IMPDEF_PERFCTR_LDST_SPEC 0x72
156−#define ARMV8_IMPDEF_PERFCTR_DP_SPEC 0x73
157−#define ARMV8_IMPDEF_PERFCTR_ASE_SPEC 0x74
158−#define ARMV8_IMPDEF_PERFCTR_VFP_SPEC 0x75
159−#define ARMV8_IMPDEF_PERFCTR_PC_WRITE_SPEC 0x76
160−#define ARMV8_IMPDEF_PERFCTR_CRYPTO_SPEC 0x77
161−#define ARMV8_IMPDEF_PERFCTR_BR_IMMED_SPEC 0x78
162−#define ARMV8_IMPDEF_PERFCTR_BR_RETURN_SPEC 0x79
163−#define ARMV8_IMPDEF_PERFCTR_BR_INDIRECT_SPEC 0x7A
164−
165−#define ARMV8_IMPDEF_PERFCTR_ISB_SPEC 0x7C
166−#define ARMV8_IMPDEF_PERFCTR_DSB_SPEC 0x7D
167−#define ARMV8_IMPDEF_PERFCTR_DMB_SPEC 0x7E
168−
169−#define ARMV8_IMPDEF_PERFCTR_EXC_UNDEF 0x81
170−#define ARMV8_IMPDEF_PERFCTR_EXC_SVC 0x82
171−#define ARMV8_IMPDEF_PERFCTR_EXC_PABORT 0x83
172−#define ARMV8_IMPDEF_PERFCTR_EXC_DABORT 0x84
173−
174−#define ARMV8_IMPDEF_PERFCTR_EXC_IRQ 0x86
175−#define ARMV8_IMPDEF_PERFCTR_EXC_FIQ 0x87
176−#define ARMV8_IMPDEF_PERFCTR_EXC_SMC 0x88
177−
178−#define ARMV8_IMPDEF_PERFCTR_EXC_HVC 0x8A
179−#define ARMV8_IMPDEF_PERFCTR_EXC_TRAP_PABORT 0x8B
180−#define ARMV8_IMPDEF_PERFCTR_EXC_TRAP_DABORT 0x8C
181−#define ARMV8_IMPDEF_PERFCTR_EXC_TRAP_OTHER 0x8D
182−#define ARMV8_IMPDEF_PERFCTR_EXC_TRAP_IRQ 0x8E
183−#define ARMV8_IMPDEF_PERFCTR_EXC_TRAP_FIQ 0x8F
184−#define ARMV8_IMPDEF_PERFCTR_RC_LD_SPEC 0x90
185−#define ARMV8_IMPDEF_PERFCTR_RC_ST_SPEC 0x91
186−
187−#define ARMV8_IMPDEF_PERFCTR_L3D_CACHE_RD 0xA0
188−#define ARMV8_IMPDEF_PERFCTR_L3D_CACHE_WR 0xA1
189−#define ARMV8_IMPDEF_PERFCTR_L3D_CACHE_REFILL_RD 0xA2
190−#define ARMV8_IMPDEF_PERFCTR_L3D_CACHE_REFILL_WR 0xA3
191−
192−#define ARMV8_IMPDEF_PERFCTR_L3D_CACHE_WB_VICTIM 0xA6
193−#define ARMV8_IMPDEF_PERFCTR_L3D_CACHE_WB_CLEAN 0xA7
194−#define ARMV8_IMPDEF_PERFCTR_L3D_CACHE_INVAL 0xA8
124+#define ARMV8_IMPDEF_PERFCTR_L1D_CACHE_RD 0x0040
125+#define ARMV8_IMPDEF_PERFCTR_L1D_CACHE_WR 0x0041
126+#define ARMV8_IMPDEF_PERFCTR_L1D_CACHE_REFILL_RD 0x0042
127+#define ARMV8_IMPDEF_PERFCTR_L1D_CACHE_REFILL_WR 0x0043
128+#define ARMV8_IMPDEF_PERFCTR_L1D_CACHE_REFILL_INNER 0x0044
129+#define ARMV8_IMPDEF_PERFCTR_L1D_CACHE_REFILL_OUTER 0x0045
130+#define ARMV8_IMPDEF_PERFCTR_L1D_CACHE_WB_VICTIM 0x0046
131+#define ARMV8_IMPDEF_PERFCTR_L1D_CACHE_WB_CLEAN 0x0047
132+#define ARMV8_IMPDEF_PERFCTR_L1D_CACHE_INVAL 0x0048
133+
134+#define ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_RD 0x004C
135+#define ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_WR 0x004D
136+#define ARMV8_IMPDEF_PERFCTR_L1D_TLB_RD 0x004E
137+#define ARMV8_IMPDEF_PERFCTR_L1D_TLB_WR 0x004F
138+#define ARMV8_IMPDEF_PERFCTR_L2D_CACHE_RD 0x0050
139+#define ARMV8_IMPDEF_PERFCTR_L2D_CACHE_WR 0x0051
140+#define ARMV8_IMPDEF_PERFCTR_L2D_CACHE_REFILL_RD 0x0052
141+#define ARMV8_IMPDEF_PERFCTR_L2D_CACHE_REFILL_WR 0x0053
142+
143+#define ARMV8_IMPDEF_PERFCTR_L2D_CACHE_WB_VICTIM 0x0056
144+#define ARMV8_IMPDEF_PERFCTR_L2D_CACHE_WB_CLEAN 0x0057
145+#define ARMV8_IMPDEF_PERFCTR_L2D_CACHE_INVAL 0x0058
146+
147+#define ARMV8_IMPDEF_PERFCTR_L2D_TLB_REFILL_RD 0x005C
148+#define ARMV8_IMPDEF_PERFCTR_L2D_TLB_REFILL_WR 0x005D
149+#define ARMV8_IMPDEF_PERFCTR_L2D_TLB_RD 0x005E
150+#define ARMV8_IMPDEF_PERFCTR_L2D_TLB_WR 0x005F
151+#define ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_RD 0x0060
152+#define ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_WR 0x0061
153+#define ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_SHARED 0x0062
154+#define ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_NOT_SHARED 0x0063
155+#define ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_NORMAL 0x0064
156+#define ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_PERIPH 0x0065
157+#define ARMV8_IMPDEF_PERFCTR_MEM_ACCESS_RD 0x0066
158+#define ARMV8_IMPDEF_PERFCTR_MEM_ACCESS_WR 0x0067
159+#define ARMV8_IMPDEF_PERFCTR_UNALIGNED_LD_SPEC 0x0068
160+#define ARMV8_IMPDEF_PERFCTR_UNALIGNED_ST_SPEC 0x0069
161+#define ARMV8_IMPDEF_PERFCTR_UNALIGNED_LDST_SPEC 0x006A
162+
163+#define ARMV8_IMPDEF_PERFCTR_LDREX_SPEC 0x006C
164+#define ARMV8_IMPDEF_PERFCTR_STREX_PASS_SPEC 0x006D
165+#define ARMV8_IMPDEF_PERFCTR_STREX_FAIL_SPEC 0x006E
166+#define ARMV8_IMPDEF_PERFCTR_STREX_SPEC 0x006F
167+#define ARMV8_IMPDEF_PERFCTR_LD_SPEC 0x0070
168+#define ARMV8_IMPDEF_PERFCTR_ST_SPEC 0x0071
169+#define ARMV8_IMPDEF_PERFCTR_LDST_SPEC 0x0072
170+#define ARMV8_IMPDEF_PERFCTR_DP_SPEC 0x0073
171+#define ARMV8_IMPDEF_PERFCTR_ASE_SPEC 0x0074
172+#define ARMV8_IMPDEF_PERFCTR_VFP_SPEC 0x0075
173+#define ARMV8_IMPDEF_PERFCTR_PC_WRITE_SPEC 0x0076
174+#define ARMV8_IMPDEF_PERFCTR_CRYPTO_SPEC 0x0077
175+#define ARMV8_IMPDEF_PERFCTR_BR_IMMED_SPEC 0x0078
176+#define ARMV8_IMPDEF_PERFCTR_BR_RETURN_SPEC 0x0079
177+#define ARMV8_IMPDEF_PERFCTR_BR_INDIRECT_SPEC 0x007A
178+
179+#define ARMV8_IMPDEF_PERFCTR_ISB_SPEC 0x007C
180+#define ARMV8_IMPDEF_PERFCTR_DSB_SPEC 0x007D
181+#define ARMV8_IMPDEF_PERFCTR_DMB_SPEC 0x007E
182+
183+#define ARMV8_IMPDEF_PERFCTR_EXC_UNDEF 0x0081
184+#define ARMV8_IMPDEF_PERFCTR_EXC_SVC 0x0082
185+#define ARMV8_IMPDEF_PERFCTR_EXC_PABORT 0x0083
186+#define ARMV8_IMPDEF_PERFCTR_EXC_DABORT 0x0084
187+
188+#define ARMV8_IMPDEF_PERFCTR_EXC_IRQ 0x0086
189+#define ARMV8_IMPDEF_PERFCTR_EXC_FIQ 0x0087
190+#define ARMV8_IMPDEF_PERFCTR_EXC_SMC 0x0088
191+
192+#define ARMV8_IMPDEF_PERFCTR_EXC_HVC 0x008A
193+#define ARMV8_IMPDEF_PERFCTR_EXC_TRAP_PABORT 0x008B
194+#define ARMV8_IMPDEF_PERFCTR_EXC_TRAP_DABORT 0x008C
195+#define ARMV8_IMPDEF_PERFCTR_EXC_TRAP_OTHER 0x008D
196+#define ARMV8_IMPDEF_PERFCTR_EXC_TRAP_IRQ 0x008E
197+#define ARMV8_IMPDEF_PERFCTR_EXC_TRAP_FIQ 0x008F
198+#define ARMV8_IMPDEF_PERFCTR_RC_LD_SPEC 0x0090
199+#define ARMV8_IMPDEF_PERFCTR_RC_ST_SPEC 0x0091
200+
201+#define ARMV8_IMPDEF_PERFCTR_L3D_CACHE_RD 0x00A0
202+#define ARMV8_IMPDEF_PERFCTR_L3D_CACHE_WR 0x00A1
203+#define ARMV8_IMPDEF_PERFCTR_L3D_CACHE_REFILL_RD 0x00A2
204+#define ARMV8_IMPDEF_PERFCTR_L3D_CACHE_REFILL_WR 0x00A3
205+
206+#define ARMV8_IMPDEF_PERFCTR_L3D_CACHE_WB_VICTIM 0x00A6
207+#define ARMV8_IMPDEF_PERFCTR_L3D_CACHE_WB_CLEAN 0x00A7
208+#define ARMV8_IMPDEF_PERFCTR_L3D_CACHE_INVAL 0x00A8
195209
196210 /*
197211 * Per-CPU PMCR: config reg
arch/arm64/kernel/perf_event.c+10−0
@@ -242,6 +242,16 @@ static struct attribute *armv8_pmuv3_event_attrs[] = { · 241 unmodified lines
242242 ARMV8_EVENT_ATTR(l2d_cache_lmiss_rd, ARMV8_PMUV3_PERFCTR_L2D_CACHE_LMISS_RD),
243243 ARMV8_EVENT_ATTR(l2i_cache_lmiss, ARMV8_PMUV3_PERFCTR_L2I_CACHE_LMISS),
244244 ARMV8_EVENT_ATTR(l3d_cache_lmiss_rd, ARMV8_PMUV3_PERFCTR_L3D_CACHE_LMISS_RD),
245+ ARMV8_EVENT_ATTR(trb_wrap, ARMV8_PMUV3_PERFCTR_TRB_WRAP),
246+ ARMV8_EVENT_ATTR(trb_trig, ARMV8_PMUV3_PERFCTR_TRB_TRIG),
247+ ARMV8_EVENT_ATTR(trcextout0, ARMV8_PMUV3_PERFCTR_TRCEXTOUT0),
248+ ARMV8_EVENT_ATTR(trcextout1, ARMV8_PMUV3_PERFCTR_TRCEXTOUT1),
249+ ARMV8_EVENT_ATTR(trcextout2, ARMV8_PMUV3_PERFCTR_TRCEXTOUT2),
250+ ARMV8_EVENT_ATTR(trcextout3, ARMV8_PMUV3_PERFCTR_TRCEXTOUT3),
251+ ARMV8_EVENT_ATTR(cti_trigout4, ARMV8_PMUV3_PERFCTR_CTI_TRIGOUT4),
252+ ARMV8_EVENT_ATTR(cti_trigout5, ARMV8_PMUV3_PERFCTR_CTI_TRIGOUT5),
253+ ARMV8_EVENT_ATTR(cti_trigout6, ARMV8_PMUV3_PERFCTR_CTI_TRIGOUT6),
254+ ARMV8_EVENT_ATTR(cti_trigout7, ARMV8_PMUV3_PERFCTR_CTI_TRIGOUT7),
245255 ARMV8_EVENT_ATTR(ldst_align_lat, ARMV8_PMUV3_PERFCTR_LDST_ALIGN_LAT),
246256 ARMV8_EVENT_ATTR(ld_align_lat, ARMV8_PMUV3_PERFCTR_LD_ALIGN_LAT),
247257 ARMV8_EVENT_ATTR(st_align_lat, ARMV8_PMUV3_PERFCTR_ST_ALIGN_LAT),
drivers/irqchip/irq-apple-aic.c+72−22
@@ -55,6 +55,7 @@ · 54 unmodified lines
5555 #include <linux/limits.h>
5656 #include <linux/of_address.h>
5757 #include <linux/slab.h>
58+#include <asm/apple_m1_pmu.h>
5859 #include <asm/exception.h>
5960 #include <asm/sysreg.h>
6061 #include <asm/virt.h>
@@ -109,16 +110,6 @@ · 48 unmodified lines
109110 * Note: sysreg-based IPIs are not supported yet.
110111 */
111112
112−/* Core PMC control register */
113−#define SYS_IMP_APL_PMCR0_EL1 sys_reg(3, 1, 15, 0, 0)
114−#define PMCR0_IMODE GENMASK(10, 8)
115−#define PMCR0_IMODE_OFF 0
116−#define PMCR0_IMODE_PMI 1
117−#define PMCR0_IMODE_AIC 2
118−#define PMCR0_IMODE_HALT 3
119−#define PMCR0_IMODE_FIQ 4
120−#define PMCR0_IACT BIT(11)
121−
122113 /* IPI request registers */
123114 #define SYS_IMP_APL_IPI_RR_LOCAL_EL1 sys_reg(3, 5, 15, 0, 0)
124115 #define SYS_IMP_APL_IPI_RR_GLOBAL_EL1 sys_reg(3, 5, 15, 0, 1)
@@ -155,7 +146,7 @@ · 30 unmodified lines
155146 #define SYS_IMP_APL_UPMSR_EL1 sys_reg(3, 7, 15, 6, 4)
156147 #define UPMSR_IACT BIT(0)
157148
158−#define AIC_NR_FIQ 4
149+#define AIC_NR_FIQ 6
159150 #define AIC_NR_SWIPI 32
160151
161152 /*
@@ -177,6 +168,9 @@ struct aic_irq_chip { · 15 unmodified lines
177168 void __iomem *base;
178169 struct irq_domain *hw_domain;
179170 struct irq_domain *ipi_domain;
171+ struct {
172+ cpumask_t aff;
173+ } *fiq_aff[AIC_NR_FIQ];
180174 int nr_hw;
181175 };
182176
@@ -412,16 +406,15 @@ static void __exception_irq_entry aic_handle_fiq(struct pt_regs *regs) · 229 unmodified lines
412406 aic_irqc->nr_hw + AIC_TMR_EL02_VIRT);
413407 }
414408
415− if ((read_sysreg_s(SYS_IMP_APL_PMCR0_EL1) & (PMCR0_IMODE | PMCR0_IACT)) ==
416− (FIELD_PREP(PMCR0_IMODE, PMCR0_IMODE_FIQ) | PMCR0_IACT)) {
417− /*
418− * Not supported yet, let's figure out how to handle this when
419− * we implement these proprietary performance counters. For now,
420− * just mask it and move on.
421− */
422− pr_err_ratelimited("PMC FIQ fired. Masking.\n");
423− sysreg_clear_set_s(SYS_IMP_APL_PMCR0_EL1, PMCR0_IMODE | PMCR0_IACT,
424− FIELD_PREP(PMCR0_IMODE, PMCR0_IMODE_OFF));
409+ if (read_sysreg_s(SYS_IMP_APL_PMCR0_EL1) & PMCR0_IACT) {
410+ int irq;
411+ if (cpumask_test_cpu(smp_processor_id(),
412+ &aic_irqc->fiq_aff[AIC_CPU_PMU_P]->aff))
413+ irq = AIC_CPU_PMU_P;
414+ else
415+ irq = AIC_CPU_PMU_E;
416+ generic_handle_domain_irq(aic_irqc->hw_domain,
417+ aic_irqc->nr_hw + irq);
425418 }
426419
427420 if (FIELD_GET(UPMCR0_IMODE, read_sysreg_s(SYS_IMP_APL_UPMCR0_EL1)) == UPMCR0_IMODE_FIQ &&
@@ -461,7 +454,18 @@ static int aic_irq_domain_map(struct irq_domain *id, unsigned int irq, · 33 unmodified lines
461454 handle_fasteoi_irq, NULL, NULL);
462455 irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(irq)));
463456 } else {
464− irq_set_percpu_devid(irq);
457+ int fiq = hw - ic->nr_hw;
458+
459+ switch (fiq) {
460+ case AIC_CPU_PMU_P:
461+ case AIC_CPU_PMU_E:
462+ irq_set_percpu_devid_partition(irq, &ic->fiq_aff[fiq]->aff);
463+ break;
464+ default:
465+ irq_set_percpu_devid(irq);
466+ break;
467+ }
468+
465469 irq_domain_set_info(id, irq, hw, &fiq_chip, id->host_data,
466470 handle_percpu_devid_irq, NULL, NULL);
467471 }
@@ -793,12 +797,50 @@ static struct gic_kvm_info vgic_info __initdata = { · 325 unmodified lines
793797 .no_hw_deactivation = true,
794798 };
795799
800+static void build_fiq_affinity(struct aic_irq_chip *ic, struct device_node *aff)
801+{
802+ int i, n;
803+ u32 fiq;
804+
805+ if (of_property_read_u32(aff, "apple,fiq-index", &fiq) ||
806+ WARN_ON(fiq >= AIC_NR_FIQ) || ic->fiq_aff[fiq])
807+ return;
808+
809+ n = of_property_count_elems_of_size(aff, "cpus", sizeof(u32));
810+ if (WARN_ON(n < 0))
811+ return;
812+
813+ ic->fiq_aff[fiq] = kzalloc(sizeof(ic->fiq_aff[fiq]), GFP_KERNEL);
814+ if (!ic->fiq_aff[fiq])
815+ return;
816+
817+ for (i = 0; i < n; i++) {
818+ struct device_node *cpu_node;
819+ u32 cpu_phandle;
820+ int cpu;
821+
822+ if (of_property_read_u32_index(aff, "cpus", i, &cpu_phandle))
823+ continue;
824+
825+ cpu_node = of_find_node_by_phandle(cpu_phandle);
826+ if (WARN_ON(!cpu_node))
827+ continue;
828+
829+ cpu = of_cpu_node_to_id(cpu_node);
830+ if (WARN_ON(cpu < 0))
831+ continue;
832+
833+ cpumask_set_cpu(cpu, &ic->fiq_aff[fiq]->aff);
834+ }
835+}
836+
796837 static int __init aic_of_ic_init(struct device_node *node, struct device_node *parent)
797838 {
798839 int i;
799840 void __iomem *regs;
800841 u32 info;
801842 struct aic_irq_chip *irqc;
843+ struct device_node *affs;
802844
803845 regs = of_iomap(node, 0);
804846 if (WARN_ON(!regs))
@@ -832,6 +874,14 @@ static int __init aic_of_ic_init(struct device_node *node, struct device_node *p · 27 unmodified lines
832874 return -ENODEV;
833875 }
834876
877+ affs = of_get_child_by_name(node, "affinities");
878+ if (affs) {
879+ struct device_node *chld;
880+
881+ for_each_child_of_node(affs, chld)
882+ build_fiq_affinity(irqc, chld);
883+ }
884+
835885 set_handle_irq(aic_handle_irq);
836886 set_handle_fiq(aic_handle_fiq);
837887
drivers/perf/Kconfig+15−1
@@ -141,11 +141,25 @@ config ARM_DMC620_PMU · 140 unmodified lines
141141
142142 config MARVELL_CN10K_TAD_PMU
143143 tristate "Marvell CN10K LLC-TAD PMU"
144− depends on ARM64 || (COMPILE_TEST && 64BIT)
144+ depends on ARCH_THUNDER || (COMPILE_TEST && 64BIT)
145145 help
146146 Provides support for Last-Level cache Tag-and-data Units (LLC-TAD)
147147 performance monitors on CN10K family silicons.
148148
149+config APPLE_M1_CPU_PMU
150+ bool "Apple M1 CPU PMU support"
151+ depends on ARM_PMU && ARCH_APPLE
152+ help
153+ Provides support for the non-architectural CPU PMUs present on
154+ the Apple M1 SoCs and derivatives.
155+
149156 source "drivers/perf/hisilicon/Kconfig"
150157
158+config MARVELL_CN10K_DDR_PMU
159+ tristate "Enable MARVELL CN10K DRAM Subsystem(DSS) PMU Support"
160+ depends on ARM64 || (COMPILE_TEST && 64BIT)
161+ help
162+ Enable perf support for Marvell DDR Performance monitoring
163+ event on CN10K platform.
164+
151165 endmenu
drivers/perf/Makefile+2−0
@@ -15,3 +15,5 @@ obj-$(CONFIG_XGENE_PMU) += xgene_pmu.o · 14 unmodified lines
1515 obj-$(CONFIG_ARM_SPE_PMU) += arm_spe_pmu.o
1616 obj-$(CONFIG_ARM_DMC620_PMU) += arm_dmc620_pmu.o
1717 obj-$(CONFIG_MARVELL_CN10K_TAD_PMU) += marvell_cn10k_tad_pmu.o
18+obj-$(CONFIG_MARVELL_CN10K_DDR_PMU) += marvell_cn10k_ddr_pmu.o
19+obj-$(CONFIG_APPLE_M1_CPU_PMU) += apple_m1_cpu_pmu.o
drivers/perf/apple_m1_cpu_pmu.c+584−0
@@ -0,0 +1,584 @@
1+// SPDX-License-Identifier: GPL-2.0
2+/*
3+ * CPU PMU driver for the Apple M1 and derivatives
4+ *
5+ * Copyright (C) 2021 Google LLC
6+ *
7+ * Author: Marc Zyngier <maz@kernel.org>
8+ *
9+ * Most of the information used in this driver was provided by the
10+ * Asahi Linux project. The rest was experimentally discovered.
11+ */
12+
13+#include <linux/of.h>
14+#include <linux/perf/arm_pmu.h>
15+#include <linux/platform_device.h>
16+
17+#include <asm/apple_m1_pmu.h>
18+#include <asm/irq_regs.h>
19+#include <asm/perf_event.h>
20+
21+#define M1_PMU_NR_COUNTERS 10
22+
23+#define M1_PMU_CFG_EVENT GENMASK(7, 0)
24+
25+#define ANY_BUT_0_1 GENMASK(9, 2)
26+#define ONLY_2_TO_7 GENMASK(7, 2)
27+#define ONLY_2_4_6 (BIT(2) | BIT(4) | BIT(6))
28+#define ONLY_5_6_7 (BIT(5) | BIT(6) | BIT(7))
29+
30+/*
31+ * Description of the events we actually know about, as well as those with
32+ * a specific counter affinity. Yes, this is a grand total of two known
33+ * counters, and the rest is anybody's guess.
34+ *
35+ * Not all counters can count all events. Counters #0 and #1 are wired to
36+ * count cycles and instructions respectively, and some events have
37+ * bizarre mappings (every other counter, or even *one* counter). These
38+ * restrictions equally apply to both P and E cores.
39+ *
40+ * It is worth noting that the PMUs attached to P and E cores are likely
41+ * to be different because the underlying uarches are different. At the
42+ * moment, we don't really need to distinguish between the two because we
43+ * know next to nothing about the events themselves, and we already have
44+ * per cpu-type PMU abstractions.
45+ *
46+ * If we eventually find out that the events are different across
47+ * implementations, we'll have to introduce per cpu-type tables.
48+ */
49+enum m1_pmu_events {
50+ M1_PMU_PERFCTR_UNKNOWN_01 = 0x01,
51+ M1_PMU_PERFCTR_CPU_CYCLES = 0x02,
52+ M1_PMU_PERFCTR_INSTRUCTIONS = 0x8c,
53+ M1_PMU_PERFCTR_UNKNOWN_8d = 0x8d,
54+ M1_PMU_PERFCTR_UNKNOWN_8e = 0x8e,
55+ M1_PMU_PERFCTR_UNKNOWN_8f = 0x8f,
56+ M1_PMU_PERFCTR_UNKNOWN_90 = 0x90,
57+ M1_PMU_PERFCTR_UNKNOWN_93 = 0x93,
58+ M1_PMU_PERFCTR_UNKNOWN_94 = 0x94,
59+ M1_PMU_PERFCTR_UNKNOWN_95 = 0x95,
60+ M1_PMU_PERFCTR_UNKNOWN_96 = 0x96,
61+ M1_PMU_PERFCTR_UNKNOWN_97 = 0x97,
62+ M1_PMU_PERFCTR_UNKNOWN_98 = 0x98,
63+ M1_PMU_PERFCTR_UNKNOWN_99 = 0x99,
64+ M1_PMU_PERFCTR_UNKNOWN_9a = 0x9a,
65+ M1_PMU_PERFCTR_UNKNOWN_9b = 0x9b,
66+ M1_PMU_PERFCTR_UNKNOWN_9c = 0x9c,
67+ M1_PMU_PERFCTR_UNKNOWN_9f = 0x9f,
68+ M1_PMU_PERFCTR_UNKNOWN_bf = 0xbf,
69+ M1_PMU_PERFCTR_UNKNOWN_c0 = 0xc0,
70+ M1_PMU_PERFCTR_UNKNOWN_c1 = 0xc1,
71+ M1_PMU_PERFCTR_UNKNOWN_c4 = 0xc4,
72+ M1_PMU_PERFCTR_UNKNOWN_c5 = 0xc5,
73+ M1_PMU_PERFCTR_UNKNOWN_c6 = 0xc6,
74+ M1_PMU_PERFCTR_UNKNOWN_c8 = 0xc8,
75+ M1_PMU_PERFCTR_UNKNOWN_ca = 0xca,
76+ M1_PMU_PERFCTR_UNKNOWN_cb = 0xcb,
77+ M1_PMU_PERFCTR_UNKNOWN_f5 = 0xf5,
78+ M1_PMU_PERFCTR_UNKNOWN_f6 = 0xf6,
79+ M1_PMU_PERFCTR_UNKNOWN_f7 = 0xf7,
80+ M1_PMU_PERFCTR_UNKNOWN_f8 = 0xf8,
81+ M1_PMU_PERFCTR_UNKNOWN_fd = 0xfd,
82+ M1_PMU_PERFCTR_LAST = M1_PMU_CFG_EVENT,
83+
84+ /*
85+ * From this point onwards, these are not actual HW events,
86+ * but attributes that get stored in hw->config_base.
87+ */
88+ M1_PMU_CFG_COUNT_USER = BIT(8),
89+ M1_PMU_CFG_COUNT_KERNEL = BIT(9),
90+};
91+
92+/*
93+ * Per-event affinity table. Most events can be installed on counter
94+ * 2-9, but there are a number of exceptions. Note that this table
95+ * has been created experimentally, and I wouldn't be surprised if more
96+ * counters had strange affinities.
97+ */
98+static const u16 m1_pmu_event_affinity[M1_PMU_PERFCTR_LAST + 1] = {
99+ [0 ... M1_PMU_PERFCTR_LAST] = ANY_BUT_0_1,
100+ [M1_PMU_PERFCTR_UNKNOWN_01] = BIT(7),
101+ [M1_PMU_PERFCTR_CPU_CYCLES] = ANY_BUT_0_1 | BIT(0),
102+ [M1_PMU_PERFCTR_INSTRUCTIONS] = BIT(7) | BIT(1),
103+ [M1_PMU_PERFCTR_UNKNOWN_8d] = ONLY_5_6_7,
104+ [M1_PMU_PERFCTR_UNKNOWN_8e] = ONLY_5_6_7,
105+ [M1_PMU_PERFCTR_UNKNOWN_8f] = ONLY_5_6_7,
106+ [M1_PMU_PERFCTR_UNKNOWN_90] = ONLY_5_6_7,
107+ [M1_PMU_PERFCTR_UNKNOWN_93] = ONLY_5_6_7,
108+ [M1_PMU_PERFCTR_UNKNOWN_94] = ONLY_5_6_7,
109+ [M1_PMU_PERFCTR_UNKNOWN_95] = ONLY_5_6_7,
110+ [M1_PMU_PERFCTR_UNKNOWN_96] = ONLY_5_6_7,
111+ [M1_PMU_PERFCTR_UNKNOWN_97] = BIT(7),
112+ [M1_PMU_PERFCTR_UNKNOWN_98] = ONLY_5_6_7,
113+ [M1_PMU_PERFCTR_UNKNOWN_99] = ONLY_5_6_7,
114+ [M1_PMU_PERFCTR_UNKNOWN_9a] = BIT(7),
115+ [M1_PMU_PERFCTR_UNKNOWN_9b] = ONLY_5_6_7,
116+ [M1_PMU_PERFCTR_UNKNOWN_9c] = ONLY_5_6_7,
117+ [M1_PMU_PERFCTR_UNKNOWN_9f] = BIT(7),
118+ [M1_PMU_PERFCTR_UNKNOWN_bf] = ONLY_5_6_7,
119+ [M1_PMU_PERFCTR_UNKNOWN_c0] = ONLY_5_6_7,
120+ [M1_PMU_PERFCTR_UNKNOWN_c1] = ONLY_5_6_7,
121+ [M1_PMU_PERFCTR_UNKNOWN_c4] = ONLY_5_6_7,
122+ [M1_PMU_PERFCTR_UNKNOWN_c5] = ONLY_5_6_7,
123+ [M1_PMU_PERFCTR_UNKNOWN_c6] = ONLY_5_6_7,
124+ [M1_PMU_PERFCTR_UNKNOWN_c8] = ONLY_5_6_7,
125+ [M1_PMU_PERFCTR_UNKNOWN_ca] = ONLY_5_6_7,
126+ [M1_PMU_PERFCTR_UNKNOWN_cb] = ONLY_5_6_7,
127+ [M1_PMU_PERFCTR_UNKNOWN_f5] = ONLY_2_4_6,
128+ [M1_PMU_PERFCTR_UNKNOWN_f6] = ONLY_2_4_6,
129+ [M1_PMU_PERFCTR_UNKNOWN_f7] = ONLY_2_4_6,
130+ [M1_PMU_PERFCTR_UNKNOWN_f8] = ONLY_2_TO_7,
131+ [M1_PMU_PERFCTR_UNKNOWN_fd] = ONLY_2_4_6,
132+};
133+
134+static const unsigned m1_pmu_perf_map[PERF_COUNT_HW_MAX] = {
135+ PERF_MAP_ALL_UNSUPPORTED,
136+ [PERF_COUNT_HW_CPU_CYCLES] = M1_PMU_PERFCTR_CPU_CYCLES,
137+ [PERF_COUNT_HW_INSTRUCTIONS] = M1_PMU_PERFCTR_INSTRUCTIONS,
138+ /* No idea about the rest yet */
139+};
140+
141+/* sysfs definitions */
142+static ssize_t m1_pmu_events_sysfs_show(struct device *dev,
143+ struct device_attribute *attr,
144+ char *page)
145+{
146+ struct perf_pmu_events_attr *pmu_attr;
147+
148+ pmu_attr = container_of(attr, struct perf_pmu_events_attr, attr);
149+
150+ return sprintf(page, "event=0x%04llx\n", pmu_attr->id);
151+}
152+
153+#define M1_PMU_EVENT_ATTR(name, config) \
154+ PMU_EVENT_ATTR_ID(name, m1_pmu_events_sysfs_show, config)
155+
156+static struct attribute *m1_pmu_event_attrs[] = {
157+ M1_PMU_EVENT_ATTR(cycles, M1_PMU_PERFCTR_CPU_CYCLES),
158+ M1_PMU_EVENT_ATTR(instructions, M1_PMU_PERFCTR_INSTRUCTIONS),
159+ NULL,
160+};
161+
162+static const struct attribute_group m1_pmu_events_attr_group = {
163+ .name = "events",
164+ .attrs = m1_pmu_event_attrs,
165+};
166+
167+PMU_FORMAT_ATTR(event, "config:0-7");
168+
169+static struct attribute *m1_pmu_format_attrs[] = {
170+ &format_attr_event.attr,
171+ NULL,
172+};
173+
174+static const struct attribute_group m1_pmu_format_attr_group = {
175+ .name = "format",
176+ .attrs = m1_pmu_format_attrs,
177+};
178+
179+/* Low level accessors. No synchronisation. */
180+#define PMU_READ_COUNTER(_idx) \
181+ case _idx: return read_sysreg_s(SYS_IMP_APL_PMC## _idx ##_EL1)
182+
183+#define PMU_WRITE_COUNTER(_val, _idx) \
184+ case _idx: \
185+ write_sysreg_s(_val, SYS_IMP_APL_PMC## _idx ##_EL1); \
186+ return
187+
188+static u64 m1_pmu_read_hw_counter(unsigned int index)
189+{
190+ switch (index) {
191+ PMU_READ_COUNTER(0);
192+ PMU_READ_COUNTER(1);
193+ PMU_READ_COUNTER(2);
194+ PMU_READ_COUNTER(3);
195+ PMU_READ_COUNTER(4);
196+ PMU_READ_COUNTER(5);
197+ PMU_READ_COUNTER(6);
198+ PMU_READ_COUNTER(7);
199+ PMU_READ_COUNTER(8);
200+ PMU_READ_COUNTER(9);
201+ }
202+
203+ BUG();
204+}
205+
206+static void m1_pmu_write_hw_counter(u64 val, unsigned int index)
207+{
208+ switch (index) {
209+ PMU_WRITE_COUNTER(val, 0);
210+ PMU_WRITE_COUNTER(val, 1);
211+ PMU_WRITE_COUNTER(val, 2);
212+ PMU_WRITE_COUNTER(val, 3);
213+ PMU_WRITE_COUNTER(val, 4);
214+ PMU_WRITE_COUNTER(val, 5);
215+ PMU_WRITE_COUNTER(val, 6);
216+ PMU_WRITE_COUNTER(val, 7);
217+ PMU_WRITE_COUNTER(val, 8);
218+ PMU_WRITE_COUNTER(val, 9);
219+ }
220+
221+ BUG();
222+}
223+
224+#define get_bit_offset(index, mask) (__ffs(mask) + (index))
225+
226+static void __m1_pmu_enable_counter(unsigned int index, bool en)
227+{
228+ u64 val, bit;
229+
230+ switch (index) {
231+ case 0 ... 7:
232+ bit = BIT(get_bit_offset(index, PMCR0_CNT_ENABLE_0_7));
233+ break;
234+ case 8 ... 9:
235+ bit = BIT(get_bit_offset(index - 8, PMCR0_CNT_ENABLE_8_9));
236+ break;
237+ default:
238+ BUG();
239+ }
240+
241+ val = read_sysreg_s(SYS_IMP_APL_PMCR0_EL1);
242+
243+ if (en)
244+ val |= bit;
245+ else
246+ val &= ~bit;
247+
248+ write_sysreg_s(val, SYS_IMP_APL_PMCR0_EL1);
249+}
250+
251+static void m1_pmu_enable_counter(unsigned int index)
252+{
253+ __m1_pmu_enable_counter(index, true);
254+}
255+
256+static void m1_pmu_disable_counter(unsigned int index)
257+{
258+ __m1_pmu_enable_counter(index, false);
259+}
260+
261+static void __m1_pmu_enable_counter_interrupt(unsigned int index, bool en)
262+{
263+ u64 val, bit;
264+
265+ switch (index) {
266+ case 0 ... 7:
267+ bit = BIT(get_bit_offset(index, PMCR0_PMI_ENABLE_0_7));
268+ break;
269+ case 8 ... 9:
270+ bit = BIT(get_bit_offset(index - 8, PMCR0_PMI_ENABLE_8_9));
271+ break;
272+ default:
273+ BUG();
274+ }
275+
276+ val = read_sysreg_s(SYS_IMP_APL_PMCR0_EL1);
277+
278+ if (en)
279+ val |= bit;
280+ else
281+ val &= ~bit;
282+
283+ write_sysreg_s(val, SYS_IMP_APL_PMCR0_EL1);
284+}
285+
286+static void m1_pmu_enable_counter_interrupt(unsigned int index)
287+{
288+ __m1_pmu_enable_counter_interrupt(index, true);
289+}
290+
291+static void m1_pmu_disable_counter_interrupt(unsigned int index)
292+{
293+ __m1_pmu_enable_counter_interrupt(index, false);
294+}
295+
296+static void m1_pmu_configure_counter(unsigned int index, u8 event,
297+ bool user, bool kernel)
298+{
299+ u64 val, user_bit, kernel_bit;
300+ int shift;
301+
302+ switch (index) {
303+ case 0 ... 7:
304+ user_bit = BIT(get_bit_offset(index, PMCR1_COUNT_A64_EL0_0_7));
305+ kernel_bit = BIT(get_bit_offset(index, PMCR1_COUNT_A64_EL1_0_7));
306+ break;
307+ case 8 ... 9:
308+ user_bit = BIT(get_bit_offset(index - 8, PMCR1_COUNT_A64_EL0_8_9));
309+ kernel_bit = BIT(get_bit_offset(index - 8, PMCR1_COUNT_A64_EL1_8_9));
310+ break;
311+ default:
312+ BUG();
313+ }
314+
315+ val = read_sysreg_s(SYS_IMP_APL_PMCR1_EL1);
316+
317+ if (user)
318+ val |= user_bit;
319+ else
320+ val &= ~user_bit;
321+
322+ if (kernel)
323+ val |= kernel_bit;
324+ else
325+ val &= ~kernel_bit;
326+
327+ write_sysreg_s(val, SYS_IMP_APL_PMCR1_EL1);
328+
329+ /*
330+ * Counters 0 and 1 have fixed events. For anything else,
331+ * place the event at the expected location in the relevant
332+ * register (PMESR0 holds the event configuration for counters
333+ * 2-5, resp. PMESR1 for counters 6-9).
334+ */
335+ switch (index) {
336+ case 0 ... 1:
337+ break;
338+ case 2 ... 5:
339+ shift = (index - 2) * 8;
340+ val = read_sysreg_s(SYS_IMP_APL_PMESR0_EL1);
341+ val &= ~((u64)0xff << shift);
342+ val |= (u64)event << shift;
343+ write_sysreg_s(val, SYS_IMP_APL_PMESR0_EL1);
344+ break;
345+ case 6 ... 9:
346+ shift = (index - 6) * 8;
347+ val = read_sysreg_s(SYS_IMP_APL_PMESR1_EL1);
348+ val &= ~((u64)0xff << shift);
349+ val |= (u64)event << shift;
350+ write_sysreg_s(val, SYS_IMP_APL_PMESR1_EL1);
351+ break;
352+ }
353+}
354+
355+/* arm_pmu backend */
356+static void m1_pmu_enable_event(struct perf_event *event)
357+{
358+ bool user, kernel;
359+ u8 evt;
360+
361+ evt = event->hw.config_base & M1_PMU_CFG_EVENT;
362+ user = event->hw.config_base & M1_PMU_CFG_COUNT_USER;
363+ kernel = event->hw.config_base & M1_PMU_CFG_COUNT_KERNEL;
364+
365+ m1_pmu_disable_counter_interrupt(event->hw.idx);
366+ m1_pmu_disable_counter(event->hw.idx);
367+ isb();
368+
369+ m1_pmu_configure_counter(event->hw.idx, evt, user, kernel);
370+ m1_pmu_enable_counter(event->hw.idx);
371+ m1_pmu_enable_counter_interrupt(event->hw.idx);
372+ isb();
373+}
374+
375+static void m1_pmu_disable_event(struct perf_event *event)
376+{
377+ m1_pmu_disable_counter_interrupt(event->hw.idx);
378+ m1_pmu_disable_counter(event->hw.idx);
379+ isb();
380+}
381+
382+static irqreturn_t m1_pmu_handle_irq(struct arm_pmu *cpu_pmu)
383+{
384+ struct pmu_hw_events *cpuc = this_cpu_ptr(cpu_pmu->hw_events);
385+ struct pt_regs *regs;
386+ u64 overflow, state;
387+ int idx;
388+
389+ overflow = read_sysreg_s(SYS_IMP_APL_PMSR_EL1);
390+ if (!overflow) {
391+ /* Spurious interrupt? */
392+ state = read_sysreg_s(SYS_IMP_APL_PMCR0_EL1);
393+ state &= ~PMCR0_IACT;
394+ write_sysreg_s(state, SYS_IMP_APL_PMCR0_EL1);
395+ isb();
396+ return IRQ_NONE;
397+ }
398+
399+ cpu_pmu->stop(cpu_pmu);
400+
401+ regs = get_irq_regs();
402+
403+ for (idx = 0; idx < cpu_pmu->num_events; idx++) {
404+ struct perf_event *event = cpuc->events[idx];
405+ struct perf_sample_data data;
406+
407+ if (!event)
408+ continue;
409+
410+ armpmu_event_update(event);
411+ perf_sample_data_init(&data, 0, event->hw.last_period);
412+ if (!armpmu_event_set_period(event))
413+ continue;
414+
415+ if (perf_event_overflow(event, &data, regs))
416+ m1_pmu_disable_event(event);
417+ }
418+
419+ cpu_pmu->start(cpu_pmu);
420+
421+ return IRQ_HANDLED;
422+}
423+
424+static u64 m1_pmu_read_counter(struct perf_event *event)
425+{
426+ return m1_pmu_read_hw_counter(event->hw.idx);
427+}
428+
429+static void m1_pmu_write_counter(struct perf_event *event, u64 value)
430+{
431+ m1_pmu_write_hw_counter(value, event->hw.idx);
432+ isb();
433+}
434+
435+static int m1_pmu_get_event_idx(struct pmu_hw_events *cpuc,
436+ struct perf_event *event)
437+{
438+ unsigned long evtype = event->hw.config_base & M1_PMU_CFG_EVENT;
439+ unsigned long affinity = m1_pmu_event_affinity[evtype];
440+ int idx;
441+
442+ /*
443+ * Place the event on the first free counter that can count
444+ * this event.
445+ *
446+ * We could do a better job if we had a view of all the events
447+ * counting on the PMU at any given time, and by placing the
448+ * most constraining events first.
449+ */
450+ for_each_set_bit(idx, &affinity, M1_PMU_NR_COUNTERS) {
451+ if (!test_and_set_bit(idx, cpuc->used_mask))
452+ return idx;
453+ }
454+
455+ return -EAGAIN;
456+}
457+
458+static void m1_pmu_clear_event_idx(struct pmu_hw_events *cpuc,
459+ struct perf_event *event)
460+{
461+ clear_bit(event->hw.idx, cpuc->used_mask);
462+}
463+
464+static void __m1_pmu_set_mode(u8 mode)
465+{
466+ u64 val;
467+
468+ val = read_sysreg_s(SYS_IMP_APL_PMCR0_EL1);
469+ val &= ~(PMCR0_IMODE | PMCR0_IACT);
470+ val |= FIELD_PREP(PMCR0_IMODE, mode);
471+ write_sysreg_s(val, SYS_IMP_APL_PMCR0_EL1);
472+ isb();
473+}
474+
475+static void m1_pmu_start(struct arm_pmu *cpu_pmu)
476+{
477+ __m1_pmu_set_mode(PMCR0_IMODE_FIQ);
478+}
479+
480+static void m1_pmu_stop(struct arm_pmu *cpu_pmu)
481+{
482+ __m1_pmu_set_mode(PMCR0_IMODE_OFF);
483+}
484+
485+static int m1_pmu_map_event(struct perf_event *event)
486+{
487+ /*
488+ * Although the counters are 48bit wide, bit 47 is what
489+ * triggers the overflow interrupt. Advertise the counters
490+ * being 47bit wide to mimick the behaviour of the ARM PMU.
491+ */
492+ event->hw.flags |= ARMPMU_EVT_47BIT;
493+ return armpmu_map_event(event, &m1_pmu_perf_map, NULL, M1_PMU_CFG_EVENT);
494+}
495+
496+static void m1_pmu_reset(void *info)
497+{
498+ int i;
499+
500+ __m1_pmu_set_mode(PMCR0_IMODE_OFF);
501+
502+ for (i = 0; i < M1_PMU_NR_COUNTERS; i++) {
503+ m1_pmu_disable_counter(i);
504+ m1_pmu_disable_counter_interrupt(i);
505+ m1_pmu_write_hw_counter(0, i);
506+ }
507+
508+ isb();
509+}
510+
511+static int m1_pmu_set_event_filter(struct hw_perf_event *event,
512+ struct perf_event_attr *attr)
513+{
514+ unsigned long config_base = 0;
515+
516+ if (!attr->exclude_guest)
517+ return -EINVAL;
518+ if (!attr->exclude_kernel)
519+ config_base |= M1_PMU_CFG_COUNT_KERNEL;
520+ if (!attr->exclude_user)
521+ config_base |= M1_PMU_CFG_COUNT_USER;
522+
523+ event->config_base = config_base;
524+
525+ return 0;
526+}
527+
528+static int m1_pmu_init(struct arm_pmu *cpu_pmu)
529+{
530+ cpu_pmu->handle_irq = m1_pmu_handle_irq;
531+ cpu_pmu->enable = m1_pmu_enable_event;
532+ cpu_pmu->disable = m1_pmu_disable_event;
533+ cpu_pmu->read_counter = m1_pmu_read_counter;
534+ cpu_pmu->write_counter = m1_pmu_write_counter;
535+ cpu_pmu->get_event_idx = m1_pmu_get_event_idx;
536+ cpu_pmu->clear_event_idx = m1_pmu_clear_event_idx;
537+ cpu_pmu->start = m1_pmu_start;
538+ cpu_pmu->stop = m1_pmu_stop;
539+ cpu_pmu->map_event = m1_pmu_map_event;
540+ cpu_pmu->reset = m1_pmu_reset;
541+ cpu_pmu->set_event_filter = m1_pmu_set_event_filter;
542+
543+ cpu_pmu->num_events = M1_PMU_NR_COUNTERS;
544+ cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_EVENTS] = &m1_pmu_events_attr_group;
545+ cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_FORMATS] = &m1_pmu_format_attr_group;
546+ return 0;
547+}
548+
549+/* Device driver gunk */
550+static int m1_pmu_ice_init(struct arm_pmu *cpu_pmu)
551+{
552+ cpu_pmu->name = "apple_icestorm_pmu";
553+ return m1_pmu_init(cpu_pmu);
554+}
555+
556+static int m1_pmu_fire_init(struct arm_pmu *cpu_pmu)
557+{
558+ cpu_pmu->name = "apple_firestorm_pmu";
559+ return m1_pmu_init(cpu_pmu);
560+}
561+
562+static const struct of_device_id m1_pmu_of_device_ids[] = {
563+ { .compatible = "apple,icestorm-pmu", .data = m1_pmu_ice_init, },
564+ { .compatible = "apple,firestorm-pmu", .data = m1_pmu_fire_init, },
565+ { },
566+};
567+MODULE_DEVICE_TABLE(of, m1_pmu_of_device_ids);
568+
569+static int m1_pmu_device_probe(struct platform_device *pdev)
570+{
571+ return arm_pmu_device_probe(pdev, m1_pmu_of_device_ids, NULL);
572+}
573+
574+static struct platform_driver m1_pmu_driver = {
575+ .driver = {
576+ .name = "apple-m1-cpu-pmu",
577+ .of_match_table = m1_pmu_of_device_ids,
578+ .suppress_bind_attrs = true,
579+ },
580+ .probe = m1_pmu_device_probe,
581+};
582+
583+module_platform_driver(m1_pmu_driver);
584+MODULE_LICENSE("GPL v2");
drivers/perf/arm-cci.c+1−1
@@ -1096,7 +1096,7 @@ static void cci_pmu_enable(struct pmu *pmu) · 1095 unmodified lines
10961096 {
10971097 struct cci_pmu *cci_pmu = to_cci_pmu(pmu);
10981098 struct cci_pmu_hw_events *hw_events = &cci_pmu->hw_events;
1099− int enabled = bitmap_weight(hw_events->used_mask, cci_pmu->num_cntrs);
1099+ bool enabled = !bitmap_empty(hw_events->used_mask, cci_pmu->num_cntrs);
11001100 unsigned long flags;
11011101
11021102 if (!enabled)
drivers/perf/arm-ccn.c+4−6
@@ -1460,8 +1460,7 @@ static irqreturn_t arm_ccn_irq_handler(int irq, void *dev_id) · 1459 unmodified lines
14601460 static int arm_ccn_probe(struct platform_device *pdev)
14611461 {
14621462 struct arm_ccn *ccn;
1463− struct resource *res;
1464− unsigned int irq;
1463+ int irq;
14651464 int err;
14661465
14671466 ccn = devm_kzalloc(&pdev->dev, sizeof(*ccn), GFP_KERNEL);
@@ -1474,10 +1473,9 @@ static int arm_ccn_probe(struct platform_device *pdev) · 6 unmodified lines
14741473 if (IS_ERR(ccn->base))
14751474 return PTR_ERR(ccn->base);
14761475
1477− res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
1478− if (!res)
1479− return -EINVAL;
1480− irq = res->start;
1476+ irq = platform_get_irq(pdev, 0);
1477+ if (irq < 0)
1478+ return irq;
14811479
14821480 /* Check if we can use the interrupt */
14831481 writel(CCN_MN_ERRINT_STATUS__PMU_EVENTS__DISABLE,
drivers/perf/arm-cmn.c+16−7
@@ -71,9 +71,11 @@ · 70 unmodified lines
7171 #define CMN_DTM_WPn(n) (0x1A0 + (n) * 0x18)
7272 #define CMN_DTM_WPn_CONFIG(n) (CMN_DTM_WPn(n) + 0x00)
7373 #define CMN_DTM_WPn_CONFIG_WP_DEV_SEL2 GENMASK_ULL(18,17)
74−#define CMN_DTM_WPn_CONFIG_WP_COMBINE BIT(6)
75−#define CMN_DTM_WPn_CONFIG_WP_EXCLUSIVE BIT(5)
76−#define CMN_DTM_WPn_CONFIG_WP_GRP BIT(4)
74+#define CMN_DTM_WPn_CONFIG_WP_COMBINE BIT(9)
75+#define CMN_DTM_WPn_CONFIG_WP_EXCLUSIVE BIT(8)
76+#define CMN600_WPn_CONFIG_WP_COMBINE BIT(6)
77+#define CMN600_WPn_CONFIG_WP_EXCLUSIVE BIT(5)
78+#define CMN_DTM_WPn_CONFIG_WP_GRP GENMASK_ULL(5, 4)
7779 #define CMN_DTM_WPn_CONFIG_WP_CHN_SEL GENMASK_ULL(3, 1)
7880 #define CMN_DTM_WPn_CONFIG_WP_DEV_SEL BIT(0)
7981 #define CMN_DTM_WPn_VAL(n) (CMN_DTM_WPn(n) + 0x08)
@@ -155,6 +157,7 @@ · 75 unmodified lines
155157 #define CMN_CONFIG_WP_COMBINE GENMASK_ULL(27, 24)
156158 #define CMN_CONFIG_WP_DEV_SEL GENMASK_ULL(50, 48)
157159 #define CMN_CONFIG_WP_CHN_SEL GENMASK_ULL(55, 51)
160+/* Note that we don't yet support the tertiary match group on newer IPs */
158161 #define CMN_CONFIG_WP_GRP BIT_ULL(56)
159162 #define CMN_CONFIG_WP_EXCLUSIVE BIT_ULL(57)
160163 #define CMN_CONFIG1_WP_VAL GENMASK_ULL(63, 0)
@@ -353,7 +356,7 @@ static struct arm_cmn_node *arm_cmn_node(const struct arm_cmn *cmn, · 192 unmodified lines
353356 return NULL;
354357 }
355358
356−struct dentry *arm_cmn_debugfs;
359+static struct dentry *arm_cmn_debugfs;
357360
358361 #ifdef CONFIG_DEBUG_FS
359362 static const char *arm_cmn_device_type(u8 type)
@@ -595,6 +598,9 @@ static umode_t arm_cmn_event_attr_is_visible(struct kobject *kobj, · 235 unmodified lines
595598 if ((intf & 4) && !(cmn->ports_used & BIT(intf & 3)))
596599 return 0;
597600
601+ if (chan == 4 && cmn->model == CMN600)
602+ return 0;
603+
598604 if ((chan == 5 && cmn->rsp_vc_num < 2) ||
599605 (chan == 6 && cmn->dat_vc_num < 2))
600606 return 0;
@@ -905,15 +911,18 @@ static u32 arm_cmn_wp_config(struct perf_event *event) · 304 unmodified lines
905911 u32 grp = CMN_EVENT_WP_GRP(event);
906912 u32 exc = CMN_EVENT_WP_EXCLUSIVE(event);
907913 u32 combine = CMN_EVENT_WP_COMBINE(event);
914+ bool is_cmn600 = to_cmn(event->pmu)->model == CMN600;
908915
909916 config = FIELD_PREP(CMN_DTM_WPn_CONFIG_WP_DEV_SEL, dev) |
910917 FIELD_PREP(CMN_DTM_WPn_CONFIG_WP_CHN_SEL, chn) |
911918 FIELD_PREP(CMN_DTM_WPn_CONFIG_WP_GRP, grp) |
912− FIELD_PREP(CMN_DTM_WPn_CONFIG_WP_EXCLUSIVE, exc) |
913919 FIELD_PREP(CMN_DTM_WPn_CONFIG_WP_DEV_SEL2, dev >> 1);
920+ if (exc)
921+ config |= is_cmn600 ? CMN600_WPn_CONFIG_WP_EXCLUSIVE :
922+ CMN_DTM_WPn_CONFIG_WP_EXCLUSIVE;
914923 if (combine && !grp)
915− config |= CMN_DTM_WPn_CONFIG_WP_COMBINE;
916−
924+ config |= is_cmn600 ? CMN600_WPn_CONFIG_WP_COMBINE :
925+ CMN_DTM_WPn_CONFIG_WP_COMBINE;
917926 return config;
918927 }
919928
drivers/perf/arm_pmu.c+4−2
@@ -109,6 +109,8 @@ static inline u64 arm_pmu_event_max_period(struct perf_event *event) · 108 unmodified lines
109109 {
110110 if (event->hw.flags & ARMPMU_EVT_64BIT)
111111 return GENMASK_ULL(63, 0);
112+ else if (event->hw.flags & ARMPMU_EVT_47BIT)
113+ return GENMASK_ULL(46, 0);
112114 else
113115 return GENMASK_ULL(31, 0);
114116 }
@@ -524,7 +526,7 @@ static void armpmu_enable(struct pmu *pmu) · 409 unmodified lines
524526 {
525527 struct arm_pmu *armpmu = to_arm_pmu(pmu);
526528 struct pmu_hw_events *hw_events = this_cpu_ptr(armpmu->hw_events);
527− int enabled = bitmap_weight(hw_events->used_mask, armpmu->num_events);
529+ bool enabled = !bitmap_empty(hw_events->used_mask, armpmu->num_events);
528530
529531 /* For task-bound events we may be called on other CPUs */
530532 if (!cpumask_test_cpu(smp_processor_id(), &armpmu->supported_cpus))
@@ -785,7 +787,7 @@ static int cpu_pm_pmu_notify(struct notifier_block *b, unsigned long cmd, · 254 unmodified lines
785787 {
786788 struct arm_pmu *armpmu = container_of(b, struct arm_pmu, cpu_pm_nb);
787789 struct pmu_hw_events *hw_events = this_cpu_ptr(armpmu->hw_events);
788− int enabled = bitmap_weight(hw_events->used_mask, armpmu->num_events);
790+ bool enabled = !bitmap_empty(hw_events->used_mask, armpmu->num_events);
789791
790792 if (!cpumask_test_cpu(smp_processor_id(), &armpmu->supported_cpus))
791793 return NOTIFY_DONE;
drivers/perf/hisilicon/hisi_uncore_pmu.c+1−1
@@ -393,7 +393,7 @@ EXPORT_SYMBOL_GPL(hisi_uncore_pmu_read); · 392 unmodified lines
393393 void hisi_uncore_pmu_enable(struct pmu *pmu)
394394 {
395395 struct hisi_pmu *hisi_pmu = to_hisi_pmu(pmu);
396− int enabled = bitmap_weight(hisi_pmu->pmu_events.used_mask,
396+ bool enabled = !bitmap_empty(hisi_pmu->pmu_events.used_mask,
397397 hisi_pmu->num_counters);
398398
399399 if (!enabled)
drivers/perf/marvell_cn10k_ddr_pmu.c+758−0
@@ -0,0 +1,758 @@
1+// SPDX-License-Identifier: GPL-2.0
2+/* Marvell CN10K DRAM Subsystem (DSS) Performance Monitor Driver
3+ *
4+ * Copyright (C) 2021 Marvell.
5+ */
6+
7+#include <linux/init.h>
8+#include <linux/io.h>
9+#include <linux/module.h>
10+#include <linux/of.h>
11+#include <linux/of_address.h>
12+#include <linux/of_device.h>
13+#include <linux/perf_event.h>
14+#include <linux/hrtimer.h>
15+
16+/* Performance Counters Operating Mode Control Registers */
17+#define DDRC_PERF_CNT_OP_MODE_CTRL 0x8020
18+#define OP_MODE_CTRL_VAL_MANNUAL 0x1
19+
20+/* Performance Counters Start Operation Control Registers */
21+#define DDRC_PERF_CNT_START_OP_CTRL 0x8028
22+#define START_OP_CTRL_VAL_START 0x1ULL
23+#define START_OP_CTRL_VAL_ACTIVE 0x2
24+
25+/* Performance Counters End Operation Control Registers */
26+#define DDRC_PERF_CNT_END_OP_CTRL 0x8030
27+#define END_OP_CTRL_VAL_END 0x1ULL
28+
29+/* Performance Counters End Status Registers */
30+#define DDRC_PERF_CNT_END_STATUS 0x8038
31+#define END_STATUS_VAL_END_TIMER_MODE_END 0x1
32+
33+/* Performance Counters Configuration Registers */
34+#define DDRC_PERF_CFG_BASE 0x8040
35+
36+/* 8 Generic event counter + 2 fixed event counters */
37+#define DDRC_PERF_NUM_GEN_COUNTERS 8
38+#define DDRC_PERF_NUM_FIX_COUNTERS 2
39+#define DDRC_PERF_READ_COUNTER_IDX DDRC_PERF_NUM_GEN_COUNTERS
40+#define DDRC_PERF_WRITE_COUNTER_IDX (DDRC_PERF_NUM_GEN_COUNTERS + 1)
41+#define DDRC_PERF_NUM_COUNTERS (DDRC_PERF_NUM_GEN_COUNTERS + \
42+ DDRC_PERF_NUM_FIX_COUNTERS)
43+
44+/* Generic event counter registers */
45+#define DDRC_PERF_CFG(n) (DDRC_PERF_CFG_BASE + 8 * (n))
46+#define EVENT_ENABLE BIT_ULL(63)
47+
48+/* Two dedicated event counters for DDR reads and writes */
49+#define EVENT_DDR_READS 101
50+#define EVENT_DDR_WRITES 100
51+
52+/*
53+ * programmable events IDs in programmable event counters.
54+ * DO NOT change these event-id numbers, they are used to
55+ * program event bitmap in h/w.
56+ */
57+#define EVENT_OP_IS_ZQLATCH 55
58+#define EVENT_OP_IS_ZQSTART 54
59+#define EVENT_OP_IS_TCR_MRR 53
60+#define EVENT_OP_IS_DQSOSC_MRR 52
61+#define EVENT_OP_IS_DQSOSC_MPC 51
62+#define EVENT_VISIBLE_WIN_LIMIT_REACHED_WR 50
63+#define EVENT_VISIBLE_WIN_LIMIT_REACHED_RD 49
64+#define EVENT_BSM_STARVATION 48
65+#define EVENT_BSM_ALLOC 47
66+#define EVENT_LPR_REQ_WITH_NOCREDIT 46
67+#define EVENT_HPR_REQ_WITH_NOCREDIT 45
68+#define EVENT_OP_IS_ZQCS 44
69+#define EVENT_OP_IS_ZQCL 43
70+#define EVENT_OP_IS_LOAD_MODE 42
71+#define EVENT_OP_IS_SPEC_REF 41
72+#define EVENT_OP_IS_CRIT_REF 40
73+#define EVENT_OP_IS_REFRESH 39
74+#define EVENT_OP_IS_ENTER_MPSM 35
75+#define EVENT_OP_IS_ENTER_POWERDOWN 31
76+#define EVENT_OP_IS_ENTER_SELFREF 27
77+#define EVENT_WAW_HAZARD 26
78+#define EVENT_RAW_HAZARD 25
79+#define EVENT_WAR_HAZARD 24
80+#define EVENT_WRITE_COMBINE 23
81+#define EVENT_RDWR_TRANSITIONS 22
82+#define EVENT_PRECHARGE_FOR_OTHER 21
83+#define EVENT_PRECHARGE_FOR_RDWR 20
84+#define EVENT_OP_IS_PRECHARGE 19
85+#define EVENT_OP_IS_MWR 18
86+#define EVENT_OP_IS_WR 17
87+#define EVENT_OP_IS_RD 16
88+#define EVENT_OP_IS_RD_ACTIVATE 15
89+#define EVENT_OP_IS_RD_OR_WR 14
90+#define EVENT_OP_IS_ACTIVATE 13
91+#define EVENT_WR_XACT_WHEN_CRITICAL 12
92+#define EVENT_LPR_XACT_WHEN_CRITICAL 11
93+#define EVENT_HPR_XACT_WHEN_CRITICAL 10
94+#define EVENT_DFI_RD_DATA_CYCLES 9
95+#define EVENT_DFI_WR_DATA_CYCLES 8
96+#define EVENT_ACT_BYPASS 7
97+#define EVENT_READ_BYPASS 6
98+#define EVENT_HIF_HI_PRI_RD 5
99+#define EVENT_HIF_RMW 4
100+#define EVENT_HIF_RD 3
101+#define EVENT_HIF_WR 2
102+#define EVENT_HIF_RD_OR_WR 1
103+
104+/* Event counter value registers */
105+#define DDRC_PERF_CNT_VALUE_BASE 0x8080
106+#define DDRC_PERF_CNT_VALUE(n) (DDRC_PERF_CNT_VALUE_BASE + 8 * (n))
107+
108+/* Fixed event counter enable/disable register */
109+#define DDRC_PERF_CNT_FREERUN_EN 0x80C0
110+#define DDRC_PERF_FREERUN_WRITE_EN 0x1
111+#define DDRC_PERF_FREERUN_READ_EN 0x2
112+
113+/* Fixed event counter control register */
114+#define DDRC_PERF_CNT_FREERUN_CTRL 0x80C8
115+#define DDRC_FREERUN_WRITE_CNT_CLR 0x1
116+#define DDRC_FREERUN_READ_CNT_CLR 0x2
117+
118+/* Fixed event counter value register */
119+#define DDRC_PERF_CNT_VALUE_WR_OP 0x80D0
120+#define DDRC_PERF_CNT_VALUE_RD_OP 0x80D8
121+#define DDRC_PERF_CNT_VALUE_OVERFLOW BIT_ULL(48)
122+#define DDRC_PERF_CNT_MAX_VALUE GENMASK_ULL(48, 0)
123+
124+struct cn10k_ddr_pmu {
125+ struct pmu pmu;
126+ void __iomem *base;
127+ unsigned int cpu;
128+ struct device *dev;
129+ int active_events;
130+ struct perf_event *events[DDRC_PERF_NUM_COUNTERS];
131+ struct hrtimer hrtimer;
132+ struct hlist_node node;
133+};
134+
135+#define to_cn10k_ddr_pmu(p) container_of(p, struct cn10k_ddr_pmu, pmu)
136+
137+static ssize_t cn10k_ddr_pmu_event_show(struct device *dev,
138+ struct device_attribute *attr,
139+ char *page)
140+{
141+ struct perf_pmu_events_attr *pmu_attr;
142+
143+ pmu_attr = container_of(attr, struct perf_pmu_events_attr, attr);
144+ return sysfs_emit(page, "event=0x%02llx\n", pmu_attr->id);
145+
146+}
147+
148+#define CN10K_DDR_PMU_EVENT_ATTR(_name, _id) \
149+ PMU_EVENT_ATTR_ID(_name, cn10k_ddr_pmu_event_show, _id)
150+
151+static struct attribute *cn10k_ddr_perf_events_attrs[] = {
152+ CN10K_DDR_PMU_EVENT_ATTR(ddr_hif_rd_or_wr_access, EVENT_HIF_RD_OR_WR),
153+ CN10K_DDR_PMU_EVENT_ATTR(ddr_hif_wr_access, EVENT_HIF_WR),
154+ CN10K_DDR_PMU_EVENT_ATTR(ddr_hif_rd_access, EVENT_HIF_RD),
155+ CN10K_DDR_PMU_EVENT_ATTR(ddr_hif_rmw_access, EVENT_HIF_RMW),
156+ CN10K_DDR_PMU_EVENT_ATTR(ddr_hif_pri_rdaccess, EVENT_HIF_HI_PRI_RD),
157+ CN10K_DDR_PMU_EVENT_ATTR(ddr_rd_bypass_access, EVENT_READ_BYPASS),
158+ CN10K_DDR_PMU_EVENT_ATTR(ddr_act_bypass_access, EVENT_ACT_BYPASS),
159+ CN10K_DDR_PMU_EVENT_ATTR(ddr_dif_wr_data_access, EVENT_DFI_WR_DATA_CYCLES),
160+ CN10K_DDR_PMU_EVENT_ATTR(ddr_dif_rd_data_access, EVENT_DFI_RD_DATA_CYCLES),
161+ CN10K_DDR_PMU_EVENT_ATTR(ddr_hpri_sched_rd_crit_access,
162+ EVENT_HPR_XACT_WHEN_CRITICAL),
163+ CN10K_DDR_PMU_EVENT_ATTR(ddr_lpri_sched_rd_crit_access,
164+ EVENT_LPR_XACT_WHEN_CRITICAL),
165+ CN10K_DDR_PMU_EVENT_ATTR(ddr_wr_trxn_crit_access,
166+ EVENT_WR_XACT_WHEN_CRITICAL),
167+ CN10K_DDR_PMU_EVENT_ATTR(ddr_cam_active_access, EVENT_OP_IS_ACTIVATE),
168+ CN10K_DDR_PMU_EVENT_ATTR(ddr_cam_rd_or_wr_access, EVENT_OP_IS_RD_OR_WR),
169+ CN10K_DDR_PMU_EVENT_ATTR(ddr_cam_rd_active_access, EVENT_OP_IS_RD_ACTIVATE),
170+ CN10K_DDR_PMU_EVENT_ATTR(ddr_cam_read, EVENT_OP_IS_RD),
171+ CN10K_DDR_PMU_EVENT_ATTR(ddr_cam_write, EVENT_OP_IS_WR),
172+ CN10K_DDR_PMU_EVENT_ATTR(ddr_cam_mwr, EVENT_OP_IS_MWR),
173+ CN10K_DDR_PMU_EVENT_ATTR(ddr_precharge, EVENT_OP_IS_PRECHARGE),
174+ CN10K_DDR_PMU_EVENT_ATTR(ddr_precharge_for_rdwr, EVENT_PRECHARGE_FOR_RDWR),
175+ CN10K_DDR_PMU_EVENT_ATTR(ddr_precharge_for_other,
176+ EVENT_PRECHARGE_FOR_OTHER),
177+ CN10K_DDR_PMU_EVENT_ATTR(ddr_rdwr_transitions, EVENT_RDWR_TRANSITIONS),
178+ CN10K_DDR_PMU_EVENT_ATTR(ddr_write_combine, EVENT_WRITE_COMBINE),
179+ CN10K_DDR_PMU_EVENT_ATTR(ddr_war_hazard, EVENT_WAR_HAZARD),
180+ CN10K_DDR_PMU_EVENT_ATTR(ddr_raw_hazard, EVENT_RAW_HAZARD),
181+ CN10K_DDR_PMU_EVENT_ATTR(ddr_waw_hazard, EVENT_WAW_HAZARD),
182+ CN10K_DDR_PMU_EVENT_ATTR(ddr_enter_selfref, EVENT_OP_IS_ENTER_SELFREF),
183+ CN10K_DDR_PMU_EVENT_ATTR(ddr_enter_powerdown, EVENT_OP_IS_ENTER_POWERDOWN),
184+ CN10K_DDR_PMU_EVENT_ATTR(ddr_enter_mpsm, EVENT_OP_IS_ENTER_MPSM),
185+ CN10K_DDR_PMU_EVENT_ATTR(ddr_refresh, EVENT_OP_IS_REFRESH),
186+ CN10K_DDR_PMU_EVENT_ATTR(ddr_crit_ref, EVENT_OP_IS_CRIT_REF),
187+ CN10K_DDR_PMU_EVENT_ATTR(ddr_spec_ref, EVENT_OP_IS_SPEC_REF),
188+ CN10K_DDR_PMU_EVENT_ATTR(ddr_load_mode, EVENT_OP_IS_LOAD_MODE),
189+ CN10K_DDR_PMU_EVENT_ATTR(ddr_zqcl, EVENT_OP_IS_ZQCL),
190+ CN10K_DDR_PMU_EVENT_ATTR(ddr_cam_wr_access, EVENT_OP_IS_ZQCS),
191+ CN10K_DDR_PMU_EVENT_ATTR(ddr_hpr_req_with_nocredit,
192+ EVENT_HPR_REQ_WITH_NOCREDIT),
193+ CN10K_DDR_PMU_EVENT_ATTR(ddr_lpr_req_with_nocredit,
194+ EVENT_LPR_REQ_WITH_NOCREDIT),
195+ CN10K_DDR_PMU_EVENT_ATTR(ddr_bsm_alloc, EVENT_BSM_ALLOC),
196+ CN10K_DDR_PMU_EVENT_ATTR(ddr_bsm_starvation, EVENT_BSM_STARVATION),
197+ CN10K_DDR_PMU_EVENT_ATTR(ddr_win_limit_reached_rd,
198+ EVENT_VISIBLE_WIN_LIMIT_REACHED_RD),
199+ CN10K_DDR_PMU_EVENT_ATTR(ddr_win_limit_reached_wr,
200+ EVENT_VISIBLE_WIN_LIMIT_REACHED_WR),
201+ CN10K_DDR_PMU_EVENT_ATTR(ddr_dqsosc_mpc, EVENT_OP_IS_DQSOSC_MPC),
202+ CN10K_DDR_PMU_EVENT_ATTR(ddr_dqsosc_mrr, EVENT_OP_IS_DQSOSC_MRR),
203+ CN10K_DDR_PMU_EVENT_ATTR(ddr_tcr_mrr, EVENT_OP_IS_TCR_MRR),
204+ CN10K_DDR_PMU_EVENT_ATTR(ddr_zqstart, EVENT_OP_IS_ZQSTART),
205+ CN10K_DDR_PMU_EVENT_ATTR(ddr_zqlatch, EVENT_OP_IS_ZQLATCH),
206+ /* Free run event counters */
207+ CN10K_DDR_PMU_EVENT_ATTR(ddr_ddr_reads, EVENT_DDR_READS),
208+ CN10K_DDR_PMU_EVENT_ATTR(ddr_ddr_writes, EVENT_DDR_WRITES),
209+ NULL
210+};
211+
212+static struct attribute_group cn10k_ddr_perf_events_attr_group = {
213+ .name = "events",
214+ .attrs = cn10k_ddr_perf_events_attrs,
215+};
216+
217+PMU_FORMAT_ATTR(event, "config:0-8");
218+
219+static struct attribute *cn10k_ddr_perf_format_attrs[] = {
220+ &format_attr_event.attr,
221+ NULL,
222+};
223+
224+static struct attribute_group cn10k_ddr_perf_format_attr_group = {
225+ .name = "format",
226+ .attrs = cn10k_ddr_perf_format_attrs,
227+};
228+
229+static ssize_t cn10k_ddr_perf_cpumask_show(struct device *dev,
230+ struct device_attribute *attr,
231+ char *buf)
232+{
233+ struct cn10k_ddr_pmu *pmu = dev_get_drvdata(dev);
234+
235+ return cpumap_print_to_pagebuf(true, buf, cpumask_of(pmu->cpu));
236+}
237+
238+static struct device_attribute cn10k_ddr_perf_cpumask_attr =
239+ __ATTR(cpumask, 0444, cn10k_ddr_perf_cpumask_show, NULL);
240+
241+static struct attribute *cn10k_ddr_perf_cpumask_attrs[] = {
242+ &cn10k_ddr_perf_cpumask_attr.attr,
243+ NULL,
244+};
245+
246+static struct attribute_group cn10k_ddr_perf_cpumask_attr_group = {
247+ .attrs = cn10k_ddr_perf_cpumask_attrs,
248+};
249+
250+static const struct attribute_group *cn10k_attr_groups[] = {
251+ &cn10k_ddr_perf_events_attr_group,
252+ &cn10k_ddr_perf_format_attr_group,
253+ &cn10k_ddr_perf_cpumask_attr_group,
254+ NULL,
255+};
256+
257+/* Default poll timeout is 100 sec, which is very sufficient for
258+ * 48 bit counter incremented max at 5.6 GT/s, which may take many
259+ * hours to overflow.
260+ */
261+static unsigned long cn10k_ddr_pmu_poll_period_sec = 100;
262+module_param_named(poll_period_sec, cn10k_ddr_pmu_poll_period_sec, ulong, 0644);
263+
264+static ktime_t cn10k_ddr_pmu_timer_period(void)
265+{
266+ return ms_to_ktime((u64)cn10k_ddr_pmu_poll_period_sec * USEC_PER_SEC);
267+}
268+
269+static int ddr_perf_get_event_bitmap(int eventid, u64 *event_bitmap)
270+{
271+ switch (eventid) {
272+ case EVENT_HIF_RD_OR_WR ... EVENT_WAW_HAZARD:
273+ case EVENT_OP_IS_REFRESH ... EVENT_OP_IS_ZQLATCH:
274+ *event_bitmap = (1ULL << (eventid - 1));
275+ break;
276+ case EVENT_OP_IS_ENTER_SELFREF:
277+ case EVENT_OP_IS_ENTER_POWERDOWN:
278+ case EVENT_OP_IS_ENTER_MPSM:
279+ *event_bitmap = (0xFULL << (eventid - 1));
280+ break;
281+ default:
282+ pr_err("%s Invalid eventid %d\n", __func__, eventid);
283+ return -EINVAL;
284+ }
285+
286+ return 0;
287+}
288+
289+static int cn10k_ddr_perf_alloc_counter(struct cn10k_ddr_pmu *pmu,
290+ struct perf_event *event)
291+{
292+ u8 config = event->attr.config;
293+ int i;
294+
295+ /* DDR read free-run counter index */
296+ if (config == EVENT_DDR_READS) {
297+ pmu->events[DDRC_PERF_READ_COUNTER_IDX] = event;
298+ return DDRC_PERF_READ_COUNTER_IDX;
299+ }
300+
301+ /* DDR write free-run counter index */
302+ if (config == EVENT_DDR_WRITES) {
303+ pmu->events[DDRC_PERF_WRITE_COUNTER_IDX] = event;
304+ return DDRC_PERF_WRITE_COUNTER_IDX;
305+ }
306+
307+ /* Allocate DDR generic counters */
308+ for (i = 0; i < DDRC_PERF_NUM_GEN_COUNTERS; i++) {
309+ if (pmu->events[i] == NULL) {
310+ pmu->events[i] = event;
311+ return i;
312+ }
313+ }
314+
315+ return -ENOENT;
316+}
317+
318+static void cn10k_ddr_perf_free_counter(struct cn10k_ddr_pmu *pmu, int counter)
319+{
320+ pmu->events[counter] = NULL;
321+}
322+
323+static int cn10k_ddr_perf_event_init(struct perf_event *event)
324+{
325+ struct cn10k_ddr_pmu *pmu = to_cn10k_ddr_pmu(event->pmu);
326+ struct hw_perf_event *hwc = &event->hw;
327+
328+ if (event->attr.type != event->pmu->type)
329+ return -ENOENT;
330+
331+ if (is_sampling_event(event)) {
332+ dev_info(pmu->dev, "Sampling not supported!\n");
333+ return -EOPNOTSUPP;
334+ }
335+
336+ if (event->cpu < 0) {
337+ dev_warn(pmu->dev, "Can't provide per-task data!\n");
338+ return -EOPNOTSUPP;
339+ }
340+
341+ /* We must NOT create groups containing mixed PMUs */
342+ if (event->group_leader->pmu != event->pmu &&
343+ !is_software_event(event->group_leader))
344+ return -EINVAL;
345+
346+ /* Set ownership of event to one CPU, same event can not be observed
347+ * on multiple cpus at same time.
348+ */
349+ event->cpu = pmu->cpu;
350+ hwc->idx = -1;
351+ return 0;
352+}
353+
354+static void cn10k_ddr_perf_counter_enable(struct cn10k_ddr_pmu *pmu,
355+ int counter, bool enable)
356+{
357+ u32 reg;
358+ u64 val;
359+
360+ if (counter > DDRC_PERF_NUM_COUNTERS) {
361+ pr_err("Error: unsupported counter %d\n", counter);
362+ return;
363+ }
364+
365+ if (counter < DDRC_PERF_NUM_GEN_COUNTERS) {
366+ reg = DDRC_PERF_CFG(counter);
367+ val = readq_relaxed(pmu->base + reg);
368+
369+ if (enable)
370+ val |= EVENT_ENABLE;
371+ else
372+ val &= ~EVENT_ENABLE;
373+
374+ writeq_relaxed(val, pmu->base + reg);
375+ } else {
376+ val = readq_relaxed(pmu->base + DDRC_PERF_CNT_FREERUN_EN);
377+ if (enable) {
378+ if (counter == DDRC_PERF_READ_COUNTER_IDX)
379+ val |= DDRC_PERF_FREERUN_READ_EN;
380+ else
381+ val |= DDRC_PERF_FREERUN_WRITE_EN;
382+ } else {
383+ if (counter == DDRC_PERF_READ_COUNTER_IDX)
384+ val &= ~DDRC_PERF_FREERUN_READ_EN;
385+ else
386+ val &= ~DDRC_PERF_FREERUN_WRITE_EN;
387+ }
388+ writeq_relaxed(val, pmu->base + DDRC_PERF_CNT_FREERUN_EN);
389+ }
390+}
391+
392+static u64 cn10k_ddr_perf_read_counter(struct cn10k_ddr_pmu *pmu, int counter)
393+{
394+ u64 val;
395+
396+ if (counter == DDRC_PERF_READ_COUNTER_IDX)
397+ return readq_relaxed(pmu->base + DDRC_PERF_CNT_VALUE_RD_OP);
398+
399+ if (counter == DDRC_PERF_WRITE_COUNTER_IDX)
400+ return readq_relaxed(pmu->base + DDRC_PERF_CNT_VALUE_WR_OP);
401+
402+ val = readq_relaxed(pmu->base + DDRC_PERF_CNT_VALUE(counter));
403+ return val;
404+}
405+
406+static void cn10k_ddr_perf_event_update(struct perf_event *event)
407+{
408+ struct cn10k_ddr_pmu *pmu = to_cn10k_ddr_pmu(event->pmu);
409+ struct hw_perf_event *hwc = &event->hw;
410+ u64 prev_count, new_count, mask;
411+
412+ do {
413+ prev_count = local64_read(&hwc->prev_count);
414+ new_count = cn10k_ddr_perf_read_counter(pmu, hwc->idx);
415+ } while (local64_xchg(&hwc->prev_count, new_count) != prev_count);
416+
417+ mask = DDRC_PERF_CNT_MAX_VALUE;
418+
419+ local64_add((new_count - prev_count) & mask, &event->count);
420+}
421+
422+static void cn10k_ddr_perf_event_start(struct perf_event *event, int flags)
423+{
424+ struct cn10k_ddr_pmu *pmu = to_cn10k_ddr_pmu(event->pmu);
425+ struct hw_perf_event *hwc = &event->hw;
426+ int counter = hwc->idx;
427+
428+ local64_set(&hwc->prev_count, 0);
429+
430+ cn10k_ddr_perf_counter_enable(pmu, counter, true);
431+
432+ hwc->state = 0;
433+}
434+
435+static int cn10k_ddr_perf_event_add(struct perf_event *event, int flags)
436+{
437+ struct cn10k_ddr_pmu *pmu = to_cn10k_ddr_pmu(event->pmu);
438+ struct hw_perf_event *hwc = &event->hw;
439+ u8 config = event->attr.config;
440+ int counter, ret;
441+ u32 reg_offset;
442+ u64 val;
443+
444+ counter = cn10k_ddr_perf_alloc_counter(pmu, event);
445+ if (counter < 0)
446+ return -EAGAIN;
447+
448+ pmu->active_events++;
449+ hwc->idx = counter;
450+
451+ if (pmu->active_events == 1)
452+ hrtimer_start(&pmu->hrtimer, cn10k_ddr_pmu_timer_period(),
453+ HRTIMER_MODE_REL_PINNED);
454+
455+ if (counter < DDRC_PERF_NUM_GEN_COUNTERS) {
456+ /* Generic counters, configure event id */
457+ reg_offset = DDRC_PERF_CFG(counter);
458+ ret = ddr_perf_get_event_bitmap(config, &val);
459+ if (ret)
460+ return ret;
461+
462+ writeq_relaxed(val, pmu->base + reg_offset);
463+ } else {
464+ /* fixed event counter, clear counter value */
465+ if (counter == DDRC_PERF_READ_COUNTER_IDX)
466+ val = DDRC_FREERUN_READ_CNT_CLR;
467+ else
468+ val = DDRC_FREERUN_WRITE_CNT_CLR;
469+
470+ writeq_relaxed(val, pmu->base + DDRC_PERF_CNT_FREERUN_CTRL);
471+ }
472+
473+ hwc->state |= PERF_HES_STOPPED;
474+
475+ if (flags & PERF_EF_START)
476+ cn10k_ddr_perf_event_start(event, flags);
477+
478+ return 0;
479+}
480+
481+static void cn10k_ddr_perf_event_stop(struct perf_event *event, int flags)
482+{
483+ struct cn10k_ddr_pmu *pmu = to_cn10k_ddr_pmu(event->pmu);
484+ struct hw_perf_event *hwc = &event->hw;
485+ int counter = hwc->idx;
486+
487+ cn10k_ddr_perf_counter_enable(pmu, counter, false);
488+
489+ if (flags & PERF_EF_UPDATE)
490+ cn10k_ddr_perf_event_update(event);
491+
492+ hwc->state |= PERF_HES_STOPPED;
493+}
494+
495+static void cn10k_ddr_perf_event_del(struct perf_event *event, int flags)
496+{
497+ struct cn10k_ddr_pmu *pmu = to_cn10k_ddr_pmu(event->pmu);
498+ struct hw_perf_event *hwc = &event->hw;
499+ int counter = hwc->idx;
500+
501+ cn10k_ddr_perf_event_stop(event, PERF_EF_UPDATE);
502+
503+ cn10k_ddr_perf_free_counter(pmu, counter);
504+ pmu->active_events--;
505+ hwc->idx = -1;
506+
507+ /* Cancel timer when no events to capture */
508+ if (pmu->active_events == 0)
509+ hrtimer_cancel(&pmu->hrtimer);
510+}
511+
512+static void cn10k_ddr_perf_pmu_enable(struct pmu *pmu)
513+{
514+ struct cn10k_ddr_pmu *ddr_pmu = to_cn10k_ddr_pmu(pmu);
515+
516+ writeq_relaxed(START_OP_CTRL_VAL_START, ddr_pmu->base +
517+ DDRC_PERF_CNT_START_OP_CTRL);
518+}
519+
520+static void cn10k_ddr_perf_pmu_disable(struct pmu *pmu)
521+{
522+ struct cn10k_ddr_pmu *ddr_pmu = to_cn10k_ddr_pmu(pmu);
523+
524+ writeq_relaxed(END_OP_CTRL_VAL_END, ddr_pmu->base +
525+ DDRC_PERF_CNT_END_OP_CTRL);
526+}
527+
528+static void cn10k_ddr_perf_event_update_all(struct cn10k_ddr_pmu *pmu)
529+{
530+ struct hw_perf_event *hwc;
531+ int i;
532+
533+ for (i = 0; i < DDRC_PERF_NUM_GEN_COUNTERS; i++) {
534+ if (pmu->events[i] == NULL)
535+ continue;
536+
537+ cn10k_ddr_perf_event_update(pmu->events[i]);
538+ }
539+
540+ /* Reset previous count as h/w counter are reset */
541+ for (i = 0; i < DDRC_PERF_NUM_GEN_COUNTERS; i++) {
542+ if (pmu->events[i] == NULL)
543+ continue;
544+
545+ hwc = &pmu->events[i]->hw;
546+ local64_set(&hwc->prev_count, 0);
547+ }
548+}
549+
550+static irqreturn_t cn10k_ddr_pmu_overflow_handler(struct cn10k_ddr_pmu *pmu)
551+{
552+ struct perf_event *event;
553+ struct hw_perf_event *hwc;
554+ u64 prev_count, new_count;
555+ u64 value;
556+ int i;
557+
558+ event = pmu->events[DDRC_PERF_READ_COUNTER_IDX];
559+ if (event) {
560+ hwc = &event->hw;
561+ prev_count = local64_read(&hwc->prev_count);
562+ new_count = cn10k_ddr_perf_read_counter(pmu, hwc->idx);
563+
564+ /* Overflow condition is when new count less than
565+ * previous count
566+ */
567+ if (new_count < prev_count)
568+ cn10k_ddr_perf_event_update(event);
569+ }
570+
571+ event = pmu->events[DDRC_PERF_WRITE_COUNTER_IDX];
572+ if (event) {
573+ hwc = &event->hw;
574+ prev_count = local64_read(&hwc->prev_count);
575+ new_count = cn10k_ddr_perf_read_counter(pmu, hwc->idx);
576+
577+ /* Overflow condition is when new count less than
578+ * previous count
579+ */
580+ if (new_count < prev_count)
581+ cn10k_ddr_perf_event_update(event);
582+ }
583+
584+ for (i = 0; i < DDRC_PERF_NUM_GEN_COUNTERS; i++) {
585+ if (pmu->events[i] == NULL)
586+ continue;
587+
588+ value = cn10k_ddr_perf_read_counter(pmu, i);
589+ if (value == DDRC_PERF_CNT_MAX_VALUE) {
590+ pr_info("Counter-(%d) reached max value\n", i);
591+ cn10k_ddr_perf_event_update_all(pmu);
592+ cn10k_ddr_perf_pmu_disable(&pmu->pmu);
593+ cn10k_ddr_perf_pmu_enable(&pmu->pmu);
594+ }
595+ }
596+
597+ return IRQ_HANDLED;
598+}
599+
600+static enum hrtimer_restart cn10k_ddr_pmu_timer_handler(struct hrtimer *hrtimer)
601+{
602+ struct cn10k_ddr_pmu *pmu = container_of(hrtimer, struct cn10k_ddr_pmu,
603+ hrtimer);
604+ unsigned long flags;
605+
606+ local_irq_save(flags);
607+ cn10k_ddr_pmu_overflow_handler(pmu);
608+ local_irq_restore(flags);
609+
610+ hrtimer_forward_now(hrtimer, cn10k_ddr_pmu_timer_period());
611+ return HRTIMER_RESTART;
612+}
613+
614+static int cn10k_ddr_pmu_offline_cpu(unsigned int cpu, struct hlist_node *node)
615+{
616+ struct cn10k_ddr_pmu *pmu = hlist_entry_safe(node, struct cn10k_ddr_pmu,
617+ node);
618+ unsigned int target;
619+
620+ if (cpu != pmu->cpu)
621+ return 0;
622+
623+ target = cpumask_any_but(cpu_online_mask, cpu);
624+ if (target >= nr_cpu_ids)
625+ return 0;
626+
627+ perf_pmu_migrate_context(&pmu->pmu, cpu, target);
628+ pmu->cpu = target;
629+ return 0;
630+}
631+
632+static int cn10k_ddr_perf_probe(struct platform_device *pdev)
633+{
634+ struct cn10k_ddr_pmu *ddr_pmu;
635+ struct resource *res;
636+ void __iomem *base;
637+ char *name;
638+ int ret;
639+
640+ ddr_pmu = devm_kzalloc(&pdev->dev, sizeof(*ddr_pmu), GFP_KERNEL);
641+ if (!ddr_pmu)
642+ return -ENOMEM;
643+
644+ ddr_pmu->dev = &pdev->dev;
645+ platform_set_drvdata(pdev, ddr_pmu);
646+
647+ base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
648+ if (IS_ERR(base))
649+ return PTR_ERR(base);
650+
651+ ddr_pmu->base = base;
652+
653+ /* Setup the PMU counter to work in manual mode */
654+ writeq_relaxed(OP_MODE_CTRL_VAL_MANNUAL, ddr_pmu->base +
655+ DDRC_PERF_CNT_OP_MODE_CTRL);
656+
657+ ddr_pmu->pmu = (struct pmu) {
658+ .module = THIS_MODULE,
659+ .capabilities = PERF_PMU_CAP_NO_EXCLUDE,
660+ .task_ctx_nr = perf_invalid_context,
661+ .attr_groups = cn10k_attr_groups,
662+ .event_init = cn10k_ddr_perf_event_init,
663+ .add = cn10k_ddr_perf_event_add,
664+ .del = cn10k_ddr_perf_event_del,
665+ .start = cn10k_ddr_perf_event_start,
666+ .stop = cn10k_ddr_perf_event_stop,
667+ .read = cn10k_ddr_perf_event_update,
668+ .pmu_enable = cn10k_ddr_perf_pmu_enable,
669+ .pmu_disable = cn10k_ddr_perf_pmu_disable,
670+ };
671+
672+ /* Choose this cpu to collect perf data */
673+ ddr_pmu->cpu = raw_smp_processor_id();
674+
675+ name = devm_kasprintf(ddr_pmu->dev, GFP_KERNEL, "mrvl_ddr_pmu_%llx",
676+ res->start);
677+ if (!name)
678+ return -ENOMEM;
679+
680+ hrtimer_init(&ddr_pmu->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
681+ ddr_pmu->hrtimer.function = cn10k_ddr_pmu_timer_handler;
682+
683+ cpuhp_state_add_instance_nocalls(
684+ CPUHP_AP_PERF_ARM_MARVELL_CN10K_DDR_ONLINE,
685+ &ddr_pmu->node);
686+
687+ ret = perf_pmu_register(&ddr_pmu->pmu, name, -1);
688+ if (ret)
689+ goto error;
690+
691+ pr_info("CN10K DDR PMU Driver for ddrc@%llx\n", res->start);
692+ return 0;
693+error:
694+ cpuhp_state_remove_instance_nocalls(
695+ CPUHP_AP_PERF_ARM_MARVELL_CN10K_DDR_ONLINE,
696+ &ddr_pmu->node);
697+ return ret;
698+}
699+
700+static int cn10k_ddr_perf_remove(struct platform_device *pdev)
701+{
702+ struct cn10k_ddr_pmu *ddr_pmu = platform_get_drvdata(pdev);
703+
704+ cpuhp_state_remove_instance_nocalls(
705+ CPUHP_AP_PERF_ARM_MARVELL_CN10K_DDR_ONLINE,
706+ &ddr_pmu->node);
707+
708+ perf_pmu_unregister(&ddr_pmu->pmu);
709+ return 0;
710+}
711+
712+#ifdef CONFIG_OF
713+static const struct of_device_id cn10k_ddr_pmu_of_match[] = {
714+ { .compatible = "marvell,cn10k-ddr-pmu", },
715+ { },
716+};
717+MODULE_DEVICE_TABLE(of, cn10k_ddr_pmu_of_match);
718+#endif
719+
720+static struct platform_driver cn10k_ddr_pmu_driver = {
721+ .driver = {
722+ .name = "cn10k-ddr-pmu",
723+ .of_match_table = of_match_ptr(cn10k_ddr_pmu_of_match),
724+ .suppress_bind_attrs = true,
725+ },
726+ .probe = cn10k_ddr_perf_probe,
727+ .remove = cn10k_ddr_perf_remove,
728+};
729+
730+static int __init cn10k_ddr_pmu_init(void)
731+{
732+ int ret;
733+
734+ ret = cpuhp_setup_state_multi(
735+ CPUHP_AP_PERF_ARM_MARVELL_CN10K_DDR_ONLINE,
736+ "perf/marvell/cn10k/ddr:online", NULL,
737+ cn10k_ddr_pmu_offline_cpu);
738+ if (ret)
739+ return ret;
740+
741+ ret = platform_driver_register(&cn10k_ddr_pmu_driver);
742+ if (ret)
743+ cpuhp_remove_multi_state(
744+ CPUHP_AP_PERF_ARM_MARVELL_CN10K_DDR_ONLINE);
745+ return ret;
746+}
747+
748+static void __exit cn10k_ddr_pmu_exit(void)
749+{
750+ platform_driver_unregister(&cn10k_ddr_pmu_driver);
751+ cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_MARVELL_CN10K_DDR_ONLINE);
752+}
753+
754+module_init(cn10k_ddr_pmu_init);
755+module_exit(cn10k_ddr_pmu_exit);
756+
757+MODULE_AUTHOR("Bharat Bhushan <bbhushan2@marvell.com>");
758+MODULE_LICENSE("GPL v2");
drivers/perf/marvell_cn10k_tad_pmu.c+2−0
@@ -368,10 +368,12 @@ static int tad_pmu_remove(struct platform_device *pdev) · 367 unmodified lines
368368 return 0;
369369 }
370370
371+#ifdef CONFIG_OF
371372 static const struct of_device_id tad_pmu_of_match[] = {
372373 { .compatible = "marvell,cn10k-tad-pmu", },
373374 {},
374375 };
376+#endif
375377
376378 static struct platform_driver tad_pmu_driver = {
377379 .driver = {
drivers/perf/thunderx2_pmu.c+2−4
@@ -887,13 +887,11 @@ static struct tx2_uncore_pmu *tx2_uncore_pmu_init_dev(struct device *dev, · 886 unmodified lines
887887 static acpi_status tx2_uncore_pmu_add(acpi_handle handle, u32 level,
888888 void *data, void **return_value)
889889 {
890+ struct acpi_device *adev = acpi_fetch_acpi_dev(handle);
890891 struct tx2_uncore_pmu *tx2_pmu;
891− struct acpi_device *adev;
892892 enum tx2_uncore_type type;
893893
894− if (acpi_bus_get_device(handle, &adev))
895− return AE_OK;
896− if (acpi_bus_get_status(adev) || !adev->status.present)
894+ if (!adev || acpi_bus_get_status(adev) || !adev->status.present)
897895 return AE_OK;
898896
899897 type = get_tx2_pmu_type(adev);
drivers/perf/xgene_pmu.c+3−5
@@ -867,7 +867,7 @@ static void xgene_perf_pmu_enable(struct pmu *pmu) · 866 unmodified lines
867867 {
868868 struct xgene_pmu_dev *pmu_dev = to_pmu_dev(pmu);
869869 struct xgene_pmu *xgene_pmu = pmu_dev->parent;
870− int enabled = bitmap_weight(pmu_dev->cntr_assign_mask,
870+ bool enabled = !bitmap_empty(pmu_dev->cntr_assign_mask,
871871 pmu_dev->max_counters);
872872
873873 if (!enabled)
@@ -1549,14 +1549,12 @@ static const struct acpi_device_id *xgene_pmu_acpi_match_type( · 675 unmodified lines
15491549 static acpi_status acpi_pmu_dev_add(acpi_handle handle, u32 level,
15501550 void *data, void **return_value)
15511551 {
1552+ struct acpi_device *adev = acpi_fetch_acpi_dev(handle);
15521553 const struct acpi_device_id *acpi_id;
15531554 struct xgene_pmu *xgene_pmu = data;
15541555 struct xgene_pmu_dev_ctx *ctx;
1555− struct acpi_device *adev;
15561556
1557− if (acpi_bus_get_device(handle, &adev))
1558− return AE_OK;
1559− if (acpi_bus_get_status(adev) || !adev->status.present)
1557+ if (!adev || acpi_bus_get_status(adev) || !adev->status.present)
15601558 return AE_OK;
15611559
15621560 acpi_id = xgene_pmu_acpi_match_type(xgene_pmu_acpi_type_match, adev);
include/dt-bindings/interrupt-controller/apple-aic.h+2−0
@@ -11,5 +11,7 @@ · 10 unmodified lines
1111 #define AIC_TMR_HV_VIRT 1
1212 #define AIC_TMR_GUEST_PHYS 2
1313 #define AIC_TMR_GUEST_VIRT 3
14+#define AIC_CPU_PMU_E 4
15+#define AIC_CPU_PMU_P 5
1416
1517 #endif
include/linux/cpuhotplug.h+1−0
@@ -231,6 +231,7 @@ enum cpuhp_state { · 230 unmodified lines
231231 CPUHP_AP_PERF_ARM_QCOM_L3_ONLINE,
232232 CPUHP_AP_PERF_ARM_APM_XGENE_ONLINE,
233233 CPUHP_AP_PERF_ARM_CAVIUM_TX2_UNCORE_ONLINE,
234+ CPUHP_AP_PERF_ARM_MARVELL_CN10K_DDR_ONLINE,
234235 CPUHP_AP_PERF_POWERPC_NEST_IMC_ONLINE,
235236 CPUHP_AP_PERF_POWERPC_CORE_IMC_ONLINE,
236237 CPUHP_AP_PERF_POWERPC_THREAD_IMC_ONLINE,
include/linux/perf/arm_pmu.h+2−0
@@ -26,6 +26,8 @@ · 25 unmodified lines
2626 */
2727 /* Event uses a 64bit counter */
2828 #define ARMPMU_EVT_64BIT 1
29+/* Event uses a 47bit counter */
30+#define ARMPMU_EVT_47BIT 2
2931
3032 #define HW_OP_UNSUPPORTED 0xFFFF
3133 #define C(_x) PERF_COUNT_HW_CACHE_##_x

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t