xref: /xnu-10002.1.13/osfmk/arm64/cpc_arm64_events.c (revision 1031c584a5e37aff177559b9f69dbd3c8c3fd30a) !
1 // Copyright (c) 2023 Apple Inc. All rights reserved.
2 //
3 // @APPLE_OSREFERENCE_LICENSE_HEADER_START@
4 //
5 // This file contains Original Code and/or Modifications of Original Code
6 // as defined in and that are subject to the Apple Public Source License
7 // Version 2.0 (the 'License'). You may not use this file except in
8 // compliance with the License. The rights granted to you under the License
9 // may not be used to create, or enable the creation or redistribution of,
10 // unlawful or unlicensed copies of an Apple operating system, or to
11 // circumvent, violate, or enable the circumvention or violation of, any
12 // terms of an Apple operating system software license agreement.
13 //
14 // Please obtain a copy of the License at
15 // http://www.opensource.apple.com/apsl/ and read it before using this file.
16 //
17 // The Original Code and all software distributed under the License are
18 // distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
19 // EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
20 // INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
21 // FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
22 // Please see the License for the specific language governing rights and
23 // limitations under the License.
24 //
25 // @APPLE_OSREFERENCE_LICENSE_HEADER_END@
26 
27 #include <arm64/cpc_arm64.h>
28 #include <kern/assert.h>
29 #include <kern/cpc.h>
30 #include <stdint.h>
31 #include <stdbool.h>
32 #include <stddef.h>
33 
34 struct cpc_event {
35 	const char *cev_name;
36 	uint16_t cev_selector;
37 };
38 
39 struct cpc_event_list {
40 	unsigned int cel_event_count;
41 	struct cpc_event cel_events[];
42 };
43 
44 static const struct cpc_event_list _cpc_known_cpmu_events;
45 static const struct cpc_event_list _cpc_known_upmu_events = {
46 	.cel_event_count = 0,
47 	.cel_events = {},
48 };
49 
50 const struct cpc_event_list *_cpc_known_events[CPC_HW_COUNT] = {
51 	[CPC_HW_CPMU] = &_cpc_known_cpmu_events,
52 	[CPC_HW_UPMU] = &_cpc_known_upmu_events,
53 };
54 
55 static const struct cpc_event *
_cpc_select_event(cpc_hw_t hw,uint16_t selector)56 _cpc_select_event(cpc_hw_t hw, uint16_t selector)
57 {
58 	assert(hw < CPC_HW_COUNT);
59 	const struct cpc_event_list *list = _cpc_known_events[hw];
60 	for (unsigned int i = 0; i < list->cel_event_count; i++) {
61 		if (list->cel_events[i].cev_selector == selector) {
62 			return &list->cel_events[i];
63 		}
64 	}
65 	return NULL;
66 }
67 
68 static
69 #if !CPC_INSECURE
70 const
71 #endif // !CPC_INSECURE
72 cpc_event_policy_t _cpc_event_policy = CPC_EVPOL_DEFAULT;
73 
74 cpc_event_policy_t
cpc_get_event_policy(void)75 cpc_get_event_policy(void)
76 {
77 	return _cpc_event_policy;
78 }
79 
80 #if CPC_INSECURE
81 
82 void
cpc_set_event_policy(cpc_event_policy_t new_policy)83 cpc_set_event_policy(cpc_event_policy_t new_policy)
84 {
85 	_cpc_event_policy = new_policy;
86 }
87 
88 #endif // CPC_INSECURE
89 
90 bool
cpc_event_allowed(cpc_hw_t hw,uint16_t event_selector)91 cpc_event_allowed(
92 	cpc_hw_t hw,
93 	uint16_t event_selector)
94 {
95 	if (event_selector == 0) {
96 		return true;
97 	}
98 	switch (_cpc_event_policy) {
99 #if CPC_INSECURE
100 	case CPC_EVPOL_ALLOW_ALL:
101 		return true;
102 #endif // CPC_INSECURE
103 	case CPC_EVPOL_DENY_ALL:
104 		return false;
105 	case CPC_EVPOL_RESTRICT_TO_KNOWN:
106 		return _cpc_select_event(hw, event_selector) != NULL;
107 	}
108 	return false;
109 }
110 
111 static const struct cpc_event_list _cpc_known_cpmu_events = {
112 #if   ARM64_BOARD_CONFIG_T6000
113 	.cel_event_count = 60,
114 	.cel_events = {
115 		{ .cev_selector = 0x0000, .cev_name = "NONE" },
116 		{ .cev_selector = 0x0001, .cev_name = "RETIRE_UOP" },
117 		{ .cev_selector = 0x0002, .cev_name = "CORE_ACTIVE_CYCLE" },
118 		{ .cev_selector = 0x0004, .cev_name = "L1I_TLB_FILL" },
119 		{ .cev_selector = 0x0005, .cev_name = "L1D_TLB_FILL" },
120 		{ .cev_selector = 0x0007, .cev_name = "MMU_TABLE_WALK_INSTRUCTION" },
121 		{ .cev_selector = 0x0008, .cev_name = "MMU_TABLE_WALK_DATA" },
122 		{ .cev_selector = 0x000a, .cev_name = "L2_TLB_MISS_INSTRUCTION" },
123 		{ .cev_selector = 0x000b, .cev_name = "L2_TLB_MISS_DATA" },
124 		{ .cev_selector = 0x000d, .cev_name = "MMU_VIRTUAL_MEMORY_FAULT_NONSPEC" },
125 		{ .cev_selector = 0x0052, .cev_name = "SCHEDULE_UOP" },
126 		{ .cev_selector = 0x006c, .cev_name = "INTERRUPT_PENDING" },
127 		{ .cev_selector = 0x0070, .cev_name = "MAP_STALL_DISPATCH" },
128 		{ .cev_selector = 0x0075, .cev_name = "MAP_REWIND" },
129 		{ .cev_selector = 0x0076, .cev_name = "MAP_STALL" },
130 		{ .cev_selector = 0x007c, .cev_name = "MAP_INT_UOP" },
131 		{ .cev_selector = 0x007d, .cev_name = "MAP_LDST_UOP" },
132 		{ .cev_selector = 0x007e, .cev_name = "MAP_SIMD_UOP" },
133 		{ .cev_selector = 0x0084, .cev_name = "FLUSH_RESTART_OTHER_NONSPEC" },
134 		{ .cev_selector = 0x008c, .cev_name = "INST_ALL" },
135 		{ .cev_selector = 0x008d, .cev_name = "INST_BRANCH" },
136 		{ .cev_selector = 0x008e, .cev_name = "INST_BRANCH_CALL" },
137 		{ .cev_selector = 0x008f, .cev_name = "INST_BRANCH_RET" },
138 		{ .cev_selector = 0x0090, .cev_name = "INST_BRANCH_TAKEN" },
139 		{ .cev_selector = 0x0093, .cev_name = "INST_BRANCH_INDIR" },
140 		{ .cev_selector = 0x0094, .cev_name = "INST_BRANCH_COND" },
141 		{ .cev_selector = 0x0095, .cev_name = "INST_INT_LD" },
142 		{ .cev_selector = 0x0096, .cev_name = "INST_INT_ST" },
143 		{ .cev_selector = 0x0097, .cev_name = "INST_INT_ALU" },
144 		{ .cev_selector = 0x0098, .cev_name = "INST_SIMD_LD" },
145 		{ .cev_selector = 0x0099, .cev_name = "INST_SIMD_ST" },
146 		{ .cev_selector = 0x009a, .cev_name = "INST_SIMD_ALU" },
147 		{ .cev_selector = 0x009b, .cev_name = "INST_LDST" },
148 		{ .cev_selector = 0x009c, .cev_name = "INST_BARRIER" },
149 		{ .cev_selector = 0x00a0, .cev_name = "L1D_TLB_ACCESS" },
150 		{ .cev_selector = 0x00a1, .cev_name = "L1D_TLB_MISS" },
151 		{ .cev_selector = 0x00a2, .cev_name = "L1D_CACHE_MISS_ST" },
152 		{ .cev_selector = 0x00a3, .cev_name = "L1D_CACHE_MISS_LD" },
153 		{ .cev_selector = 0x00a6, .cev_name = "LD_UNIT_UOP" },
154 		{ .cev_selector = 0x00a7, .cev_name = "ST_UNIT_UOP" },
155 		{ .cev_selector = 0x00a8, .cev_name = "L1D_CACHE_WRITEBACK" },
156 		{ .cev_selector = 0x00b1, .cev_name = "LDST_X64_UOP" },
157 		{ .cev_selector = 0x00b2, .cev_name = "LDST_XPG_UOP" },
158 		{ .cev_selector = 0x00b3, .cev_name = "ATOMIC_OR_EXCLUSIVE_SUCC" },
159 		{ .cev_selector = 0x00b4, .cev_name = "ATOMIC_OR_EXCLUSIVE_FAIL" },
160 		{ .cev_selector = 0x00bf, .cev_name = "L1D_CACHE_MISS_LD_NONSPEC" },
161 		{ .cev_selector = 0x00c0, .cev_name = "L1D_CACHE_MISS_ST_NONSPEC" },
162 		{ .cev_selector = 0x00c1, .cev_name = "L1D_TLB_MISS_NONSPEC" },
163 		{ .cev_selector = 0x00c4, .cev_name = "ST_MEMORY_ORDER_VIOLATION_NONSPEC" },
164 		{ .cev_selector = 0x00c5, .cev_name = "BRANCH_COND_MISPRED_NONSPEC" },
165 		{ .cev_selector = 0x00c6, .cev_name = "BRANCH_INDIR_MISPRED_NONSPEC" },
166 		{ .cev_selector = 0x00c8, .cev_name = "BRANCH_RET_INDIR_MISPRED_NONSPEC" },
167 		{ .cev_selector = 0x00ca, .cev_name = "BRANCH_CALL_INDIR_MISPRED_NONSPEC" },
168 		{ .cev_selector = 0x00cb, .cev_name = "BRANCH_MISPRED_NONSPEC" },
169 		{ .cev_selector = 0x00d4, .cev_name = "L1I_TLB_MISS_DEMAND" },
170 		{ .cev_selector = 0x00d6, .cev_name = "MAP_DISPATCH_BUBBLE" },
171 		{ .cev_selector = 0x00db, .cev_name = "L1I_CACHE_MISS_DEMAND" },
172 		{ .cev_selector = 0x00de, .cev_name = "FETCH_RESTART" },
173 		{ .cev_selector = 0x00e5, .cev_name = "ST_NT_UOP" },
174 		{ .cev_selector = 0x00e6, .cev_name = "LD_NT_UOP" },
175 	},
176 #elif ARM64_BOARD_CONFIG_T8101
177 	.cel_event_count = 60,
178 	.cel_events = {
179 		{ .cev_selector = 0x0000, .cev_name = "NONE" },
180 		{ .cev_selector = 0x0001, .cev_name = "RETIRE_UOP" },
181 		{ .cev_selector = 0x0002, .cev_name = "CORE_ACTIVE_CYCLE" },
182 		{ .cev_selector = 0x0004, .cev_name = "L1I_TLB_FILL" },
183 		{ .cev_selector = 0x0005, .cev_name = "L1D_TLB_FILL" },
184 		{ .cev_selector = 0x0007, .cev_name = "MMU_TABLE_WALK_INSTRUCTION" },
185 		{ .cev_selector = 0x0008, .cev_name = "MMU_TABLE_WALK_DATA" },
186 		{ .cev_selector = 0x000a, .cev_name = "L2_TLB_MISS_INSTRUCTION" },
187 		{ .cev_selector = 0x000b, .cev_name = "L2_TLB_MISS_DATA" },
188 		{ .cev_selector = 0x000d, .cev_name = "MMU_VIRTUAL_MEMORY_FAULT_NONSPEC" },
189 		{ .cev_selector = 0x0052, .cev_name = "SCHEDULE_UOP" },
190 		{ .cev_selector = 0x006c, .cev_name = "INTERRUPT_PENDING" },
191 		{ .cev_selector = 0x0070, .cev_name = "MAP_STALL_DISPATCH" },
192 		{ .cev_selector = 0x0075, .cev_name = "MAP_REWIND" },
193 		{ .cev_selector = 0x0076, .cev_name = "MAP_STALL" },
194 		{ .cev_selector = 0x007c, .cev_name = "MAP_INT_UOP" },
195 		{ .cev_selector = 0x007d, .cev_name = "MAP_LDST_UOP" },
196 		{ .cev_selector = 0x007e, .cev_name = "MAP_SIMD_UOP" },
197 		{ .cev_selector = 0x0084, .cev_name = "FLUSH_RESTART_OTHER_NONSPEC" },
198 		{ .cev_selector = 0x008c, .cev_name = "INST_ALL" },
199 		{ .cev_selector = 0x008d, .cev_name = "INST_BRANCH" },
200 		{ .cev_selector = 0x008e, .cev_name = "INST_BRANCH_CALL" },
201 		{ .cev_selector = 0x008f, .cev_name = "INST_BRANCH_RET" },
202 		{ .cev_selector = 0x0090, .cev_name = "INST_BRANCH_TAKEN" },
203 		{ .cev_selector = 0x0093, .cev_name = "INST_BRANCH_INDIR" },
204 		{ .cev_selector = 0x0094, .cev_name = "INST_BRANCH_COND" },
205 		{ .cev_selector = 0x0095, .cev_name = "INST_INT_LD" },
206 		{ .cev_selector = 0x0096, .cev_name = "INST_INT_ST" },
207 		{ .cev_selector = 0x0097, .cev_name = "INST_INT_ALU" },
208 		{ .cev_selector = 0x0098, .cev_name = "INST_SIMD_LD" },
209 		{ .cev_selector = 0x0099, .cev_name = "INST_SIMD_ST" },
210 		{ .cev_selector = 0x009a, .cev_name = "INST_SIMD_ALU" },
211 		{ .cev_selector = 0x009b, .cev_name = "INST_LDST" },
212 		{ .cev_selector = 0x009c, .cev_name = "INST_BARRIER" },
213 		{ .cev_selector = 0x00a0, .cev_name = "L1D_TLB_ACCESS" },
214 		{ .cev_selector = 0x00a1, .cev_name = "L1D_TLB_MISS" },
215 		{ .cev_selector = 0x00a2, .cev_name = "L1D_CACHE_MISS_ST" },
216 		{ .cev_selector = 0x00a3, .cev_name = "L1D_CACHE_MISS_LD" },
217 		{ .cev_selector = 0x00a6, .cev_name = "LD_UNIT_UOP" },
218 		{ .cev_selector = 0x00a7, .cev_name = "ST_UNIT_UOP" },
219 		{ .cev_selector = 0x00a8, .cev_name = "L1D_CACHE_WRITEBACK" },
220 		{ .cev_selector = 0x00b1, .cev_name = "LDST_X64_UOP" },
221 		{ .cev_selector = 0x00b2, .cev_name = "LDST_XPG_UOP" },
222 		{ .cev_selector = 0x00b3, .cev_name = "ATOMIC_OR_EXCLUSIVE_SUCC" },
223 		{ .cev_selector = 0x00b4, .cev_name = "ATOMIC_OR_EXCLUSIVE_FAIL" },
224 		{ .cev_selector = 0x00bf, .cev_name = "L1D_CACHE_MISS_LD_NONSPEC" },
225 		{ .cev_selector = 0x00c0, .cev_name = "L1D_CACHE_MISS_ST_NONSPEC" },
226 		{ .cev_selector = 0x00c1, .cev_name = "L1D_TLB_MISS_NONSPEC" },
227 		{ .cev_selector = 0x00c4, .cev_name = "ST_MEMORY_ORDER_VIOLATION_NONSPEC" },
228 		{ .cev_selector = 0x00c5, .cev_name = "BRANCH_COND_MISPRED_NONSPEC" },
229 		{ .cev_selector = 0x00c6, .cev_name = "BRANCH_INDIR_MISPRED_NONSPEC" },
230 		{ .cev_selector = 0x00c8, .cev_name = "BRANCH_RET_INDIR_MISPRED_NONSPEC" },
231 		{ .cev_selector = 0x00ca, .cev_name = "BRANCH_CALL_INDIR_MISPRED_NONSPEC" },
232 		{ .cev_selector = 0x00cb, .cev_name = "BRANCH_MISPRED_NONSPEC" },
233 		{ .cev_selector = 0x00d4, .cev_name = "L1I_TLB_MISS_DEMAND" },
234 		{ .cev_selector = 0x00d6, .cev_name = "MAP_DISPATCH_BUBBLE" },
235 		{ .cev_selector = 0x00db, .cev_name = "L1I_CACHE_MISS_DEMAND" },
236 		{ .cev_selector = 0x00de, .cev_name = "FETCH_RESTART" },
237 		{ .cev_selector = 0x00e5, .cev_name = "ST_NT_UOP" },
238 		{ .cev_selector = 0x00e6, .cev_name = "LD_NT_UOP" },
239 	},
240 #elif ARM64_BOARD_CONFIG_T8103
241 	.cel_event_count = 60,
242 	.cel_events = {
243 		{ .cev_selector = 0x0000, .cev_name = "NONE" },
244 		{ .cev_selector = 0x0001, .cev_name = "RETIRE_UOP" },
245 		{ .cev_selector = 0x0002, .cev_name = "CORE_ACTIVE_CYCLE" },
246 		{ .cev_selector = 0x0004, .cev_name = "L1I_TLB_FILL" },
247 		{ .cev_selector = 0x0005, .cev_name = "L1D_TLB_FILL" },
248 		{ .cev_selector = 0x0007, .cev_name = "MMU_TABLE_WALK_INSTRUCTION" },
249 		{ .cev_selector = 0x0008, .cev_name = "MMU_TABLE_WALK_DATA" },
250 		{ .cev_selector = 0x000a, .cev_name = "L2_TLB_MISS_INSTRUCTION" },
251 		{ .cev_selector = 0x000b, .cev_name = "L2_TLB_MISS_DATA" },
252 		{ .cev_selector = 0x000d, .cev_name = "MMU_VIRTUAL_MEMORY_FAULT_NONSPEC" },
253 		{ .cev_selector = 0x0052, .cev_name = "SCHEDULE_UOP" },
254 		{ .cev_selector = 0x006c, .cev_name = "INTERRUPT_PENDING" },
255 		{ .cev_selector = 0x0070, .cev_name = "MAP_STALL_DISPATCH" },
256 		{ .cev_selector = 0x0075, .cev_name = "MAP_REWIND" },
257 		{ .cev_selector = 0x0076, .cev_name = "MAP_STALL" },
258 		{ .cev_selector = 0x007c, .cev_name = "MAP_INT_UOP" },
259 		{ .cev_selector = 0x007d, .cev_name = "MAP_LDST_UOP" },
260 		{ .cev_selector = 0x007e, .cev_name = "MAP_SIMD_UOP" },
261 		{ .cev_selector = 0x0084, .cev_name = "FLUSH_RESTART_OTHER_NONSPEC" },
262 		{ .cev_selector = 0x008c, .cev_name = "INST_ALL" },
263 		{ .cev_selector = 0x008d, .cev_name = "INST_BRANCH" },
264 		{ .cev_selector = 0x008e, .cev_name = "INST_BRANCH_CALL" },
265 		{ .cev_selector = 0x008f, .cev_name = "INST_BRANCH_RET" },
266 		{ .cev_selector = 0x0090, .cev_name = "INST_BRANCH_TAKEN" },
267 		{ .cev_selector = 0x0093, .cev_name = "INST_BRANCH_INDIR" },
268 		{ .cev_selector = 0x0094, .cev_name = "INST_BRANCH_COND" },
269 		{ .cev_selector = 0x0095, .cev_name = "INST_INT_LD" },
270 		{ .cev_selector = 0x0096, .cev_name = "INST_INT_ST" },
271 		{ .cev_selector = 0x0097, .cev_name = "INST_INT_ALU" },
272 		{ .cev_selector = 0x0098, .cev_name = "INST_SIMD_LD" },
273 		{ .cev_selector = 0x0099, .cev_name = "INST_SIMD_ST" },
274 		{ .cev_selector = 0x009a, .cev_name = "INST_SIMD_ALU" },
275 		{ .cev_selector = 0x009b, .cev_name = "INST_LDST" },
276 		{ .cev_selector = 0x009c, .cev_name = "INST_BARRIER" },
277 		{ .cev_selector = 0x00a0, .cev_name = "L1D_TLB_ACCESS" },
278 		{ .cev_selector = 0x00a1, .cev_name = "L1D_TLB_MISS" },
279 		{ .cev_selector = 0x00a2, .cev_name = "L1D_CACHE_MISS_ST" },
280 		{ .cev_selector = 0x00a3, .cev_name = "L1D_CACHE_MISS_LD" },
281 		{ .cev_selector = 0x00a6, .cev_name = "LD_UNIT_UOP" },
282 		{ .cev_selector = 0x00a7, .cev_name = "ST_UNIT_UOP" },
283 		{ .cev_selector = 0x00a8, .cev_name = "L1D_CACHE_WRITEBACK" },
284 		{ .cev_selector = 0x00b1, .cev_name = "LDST_X64_UOP" },
285 		{ .cev_selector = 0x00b2, .cev_name = "LDST_XPG_UOP" },
286 		{ .cev_selector = 0x00b3, .cev_name = "ATOMIC_OR_EXCLUSIVE_SUCC" },
287 		{ .cev_selector = 0x00b4, .cev_name = "ATOMIC_OR_EXCLUSIVE_FAIL" },
288 		{ .cev_selector = 0x00bf, .cev_name = "L1D_CACHE_MISS_LD_NONSPEC" },
289 		{ .cev_selector = 0x00c0, .cev_name = "L1D_CACHE_MISS_ST_NONSPEC" },
290 		{ .cev_selector = 0x00c1, .cev_name = "L1D_TLB_MISS_NONSPEC" },
291 		{ .cev_selector = 0x00c4, .cev_name = "ST_MEMORY_ORDER_VIOLATION_NONSPEC" },
292 		{ .cev_selector = 0x00c5, .cev_name = "BRANCH_COND_MISPRED_NONSPEC" },
293 		{ .cev_selector = 0x00c6, .cev_name = "BRANCH_INDIR_MISPRED_NONSPEC" },
294 		{ .cev_selector = 0x00c8, .cev_name = "BRANCH_RET_INDIR_MISPRED_NONSPEC" },
295 		{ .cev_selector = 0x00ca, .cev_name = "BRANCH_CALL_INDIR_MISPRED_NONSPEC" },
296 		{ .cev_selector = 0x00cb, .cev_name = "BRANCH_MISPRED_NONSPEC" },
297 		{ .cev_selector = 0x00d4, .cev_name = "L1I_TLB_MISS_DEMAND" },
298 		{ .cev_selector = 0x00d6, .cev_name = "MAP_DISPATCH_BUBBLE" },
299 		{ .cev_selector = 0x00db, .cev_name = "L1I_CACHE_MISS_DEMAND" },
300 		{ .cev_selector = 0x00de, .cev_name = "FETCH_RESTART" },
301 		{ .cev_selector = 0x00e5, .cev_name = "ST_NT_UOP" },
302 		{ .cev_selector = 0x00e6, .cev_name = "LD_NT_UOP" },
303 	},
304 #else
305 	.cel_event_count = 0,
306 	.cel_events = {},
307 #endif
308 };
309