1 // SPDX-License-Identifier: GPL-2.0+
2 //
3 // Copyright 2019 Madhavan Srinivasan, IBM Corporation.
4 
5 #define pr_fmt(fmt)	"generic-compat-pmu: " fmt
6 
7 #include "isa207-common.h"
8 
9 /*
10  * Raw event encoding:
11  *
12  *        60        56        52        48        44        40        36        32
13  * | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - |
14  *
15  *        28        24        20        16        12         8         4         0
16  * | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - |
17  *                                 [ pmc ]   [unit ]   [ ]   m   [    pmcxsel    ]
18  *                                                     |     |
19  *                                                     |     *- mark
20  *                                                     |
21  *                                                     |
22  *                                                     *- combine
23  *
24  * Below uses IBM bit numbering.
25  *
26  * MMCR1[x:y] = unit    (PMCxUNIT)
27  * MMCR1[24]   = pmc1combine[0]
28  * MMCR1[25]   = pmc1combine[1]
29  * MMCR1[26]   = pmc2combine[0]
30  * MMCR1[27]   = pmc2combine[1]
31  * MMCR1[28]   = pmc3combine[0]
32  * MMCR1[29]   = pmc3combine[1]
33  * MMCR1[30]   = pmc4combine[0]
34  * MMCR1[31]   = pmc4combine[1]
35  *
36  */
37 
38 /*
39  * Some power9 event codes.
40  */
41 #define EVENT(_name, _code)	_name = _code,
42 
43 enum {
44 EVENT(PM_CYC,					0x0001e)
45 EVENT(PM_INST_CMPL,				0x00002)
46 };
47 
48 #undef EVENT
49 
50 GENERIC_EVENT_ATTR(cpu-cycles,			PM_CYC);
51 GENERIC_EVENT_ATTR(instructions,		PM_INST_CMPL);
52 
53 static struct attribute *generic_compat_events_attr[] = {
54 	GENERIC_EVENT_PTR(PM_CYC),
55 	GENERIC_EVENT_PTR(PM_INST_CMPL),
56 	NULL
57 };
58 
59 static struct attribute_group generic_compat_pmu_events_group = {
60 	.name = "events",
61 	.attrs = generic_compat_events_attr,
62 };
63 
64 PMU_FORMAT_ATTR(event,		"config:0-19");
65 PMU_FORMAT_ATTR(pmcxsel,	"config:0-7");
66 PMU_FORMAT_ATTR(mark,		"config:8");
67 PMU_FORMAT_ATTR(combine,	"config:10-11");
68 PMU_FORMAT_ATTR(unit,		"config:12-15");
69 PMU_FORMAT_ATTR(pmc,		"config:16-19");
70 
71 static struct attribute *generic_compat_pmu_format_attr[] = {
72 	&format_attr_event.attr,
73 	&format_attr_pmcxsel.attr,
74 	&format_attr_mark.attr,
75 	&format_attr_combine.attr,
76 	&format_attr_unit.attr,
77 	&format_attr_pmc.attr,
78 	NULL,
79 };
80 
81 static struct attribute_group generic_compat_pmu_format_group = {
82 	.name = "format",
83 	.attrs = generic_compat_pmu_format_attr,
84 };
85 
86 static const struct attribute_group *generic_compat_pmu_attr_groups[] = {
87 	&generic_compat_pmu_format_group,
88 	&generic_compat_pmu_events_group,
89 	NULL,
90 };
91 
92 static int compat_generic_events[] = {
93 	[PERF_COUNT_HW_CPU_CYCLES] =			PM_CYC,
94 	[PERF_COUNT_HW_INSTRUCTIONS] =			PM_INST_CMPL,
95 };
96 
97 #define C(x)	PERF_COUNT_HW_CACHE_##x
98 
99 /*
100  * Table of generalized cache-related events.
101  * 0 means not supported, -1 means nonsensical, other values
102  * are event codes.
103  */
104 static int generic_compat_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
105 	[ C(L1D) ] = {
106 		[ C(OP_READ) ] = {
107 			[ C(RESULT_ACCESS) ] = 0,
108 			[ C(RESULT_MISS)   ] = 0,
109 		},
110 		[ C(OP_WRITE) ] = {
111 			[ C(RESULT_ACCESS) ] = 0,
112 			[ C(RESULT_MISS)   ] = 0,
113 		},
114 		[ C(OP_PREFETCH) ] = {
115 			[ C(RESULT_ACCESS) ] = 0,
116 			[ C(RESULT_MISS)   ] = 0,
117 		},
118 	},
119 	[ C(L1I) ] = {
120 		[ C(OP_READ) ] = {
121 			[ C(RESULT_ACCESS) ] = 0,
122 			[ C(RESULT_MISS)   ] = 0,
123 		},
124 		[ C(OP_WRITE) ] = {
125 			[ C(RESULT_ACCESS) ] = 0,
126 			[ C(RESULT_MISS)   ] = -1,
127 		},
128 		[ C(OP_PREFETCH) ] = {
129 			[ C(RESULT_ACCESS) ] = 0,
130 			[ C(RESULT_MISS)   ] = 0,
131 		},
132 	},
133 	[ C(LL) ] = {
134 		[ C(OP_READ) ] = {
135 			[ C(RESULT_ACCESS) ] = 0,
136 			[ C(RESULT_MISS)   ] = 0,
137 		},
138 		[ C(OP_WRITE) ] = {
139 			[ C(RESULT_ACCESS) ] = 0,
140 			[ C(RESULT_MISS)   ] = 0,
141 		},
142 		[ C(OP_PREFETCH) ] = {
143 			[ C(RESULT_ACCESS) ] = 0,
144 			[ C(RESULT_MISS)   ] = 0,
145 		},
146 	},
147 	[ C(DTLB) ] = {
148 		[ C(OP_READ) ] = {
149 			[ C(RESULT_ACCESS) ] = 0,
150 			[ C(RESULT_MISS)   ] = 0,
151 		},
152 		[ C(OP_WRITE) ] = {
153 			[ C(RESULT_ACCESS) ] = -1,
154 			[ C(RESULT_MISS)   ] = -1,
155 		},
156 		[ C(OP_PREFETCH) ] = {
157 			[ C(RESULT_ACCESS) ] = -1,
158 			[ C(RESULT_MISS)   ] = -1,
159 		},
160 	},
161 	[ C(ITLB) ] = {
162 		[ C(OP_READ) ] = {
163 			[ C(RESULT_ACCESS) ] = 0,
164 			[ C(RESULT_MISS)   ] = 0,
165 		},
166 		[ C(OP_WRITE) ] = {
167 			[ C(RESULT_ACCESS) ] = -1,
168 			[ C(RESULT_MISS)   ] = -1,
169 		},
170 		[ C(OP_PREFETCH) ] = {
171 			[ C(RESULT_ACCESS) ] = -1,
172 			[ C(RESULT_MISS)   ] = -1,
173 		},
174 	},
175 	[ C(BPU) ] = {
176 		[ C(OP_READ) ] = {
177 			[ C(RESULT_ACCESS) ] = 0,
178 			[ C(RESULT_MISS)   ] = 0,
179 		},
180 		[ C(OP_WRITE) ] = {
181 			[ C(RESULT_ACCESS) ] = -1,
182 			[ C(RESULT_MISS)   ] = -1,
183 		},
184 		[ C(OP_PREFETCH) ] = {
185 			[ C(RESULT_ACCESS) ] = -1,
186 			[ C(RESULT_MISS)   ] = -1,
187 		},
188 	},
189 	[ C(NODE) ] = {
190 		[ C(OP_READ) ] = {
191 			[ C(RESULT_ACCESS) ] = -1,
192 			[ C(RESULT_MISS)   ] = -1,
193 		},
194 		[ C(OP_WRITE) ] = {
195 			[ C(RESULT_ACCESS) ] = -1,
196 			[ C(RESULT_MISS)   ] = -1,
197 		},
198 		[ C(OP_PREFETCH) ] = {
199 			[ C(RESULT_ACCESS) ] = -1,
200 			[ C(RESULT_MISS)   ] = -1,
201 		},
202 	},
203 };
204 
205 #undef C
206 
207 static struct power_pmu generic_compat_pmu = {
208 	.name			= "GENERIC_COMPAT",
209 	.n_counter		= MAX_PMU_COUNTERS,
210 	.add_fields		= ISA207_ADD_FIELDS,
211 	.test_adder		= ISA207_TEST_ADDER,
212 	.compute_mmcr		= isa207_compute_mmcr,
213 	.get_constraint		= isa207_get_constraint,
214 	.disable_pmc		= isa207_disable_pmc,
215 	.flags			= PPMU_HAS_SIER | PPMU_ARCH_207S,
216 	.n_generic		= ARRAY_SIZE(compat_generic_events),
217 	.generic_events		= compat_generic_events,
218 	.cache_events		= &generic_compat_cache_events,
219 	.attr_groups		= generic_compat_pmu_attr_groups,
220 };
221 
222 int init_generic_compat_pmu(void)
223 {
224 	int rc = 0;
225 
226 	rc = register_power_pmu(&generic_compat_pmu);
227 	if (rc)
228 		return rc;
229 
230 	/* Tell userspace that EBB is supported */
231 	cur_cpu_spec->cpu_user_features2 |= PPC_FEATURE2_EBB;
232 
233 	return 0;
234 }
235