1 /*
2 * Copyright (c) 2017-2020 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29 #include <arm/cpu_data_internal.h>
30 #include <arm/machine_routines.h>
31 #include <arm64/monotonic.h>
32 #include <kern/assert.h>
33 #include <kern/debug.h> /* panic */
34 #include <kern/kpc.h>
35 #include <kern/monotonic.h>
36 #include <machine/atomic.h>
37 #include <machine/limits.h> /* CHAR_BIT */
38 #include <os/overflow.h>
39 #include <pexpert/arm64/board_config.h>
40 #include <pexpert/device_tree.h> /* SecureDTFindEntry */
41 #include <pexpert/pexpert.h>
42 #include <stdatomic.h>
43 #include <stdint.h>
44 #include <string.h>
45 #include <sys/errno.h>
46 #include <sys/monotonic.h>
47
48 /*
49 * Ensure that control registers read back what was written under MACH_ASSERT
50 * kernels.
51 *
52 * A static inline function cannot be used due to passing the register through
53 * the builtin -- it requires a constant string as its first argument, since
54 * MSRs registers are encoded as an immediate in the instruction.
55 */
56 #if MACH_ASSERT
57 #define CTRL_REG_SET(reg, val) do { \
58 __builtin_arm_wsr64((reg), (val)); \
59 uint64_t __check_reg = __builtin_arm_rsr64((reg)); \
60 if (__check_reg != (val)) { \
61 panic("value written to %s was not read back (wrote %llx, read %llx)", \
62 #reg, (val), __check_reg); \
63 } \
64 } while (0)
65 #else /* MACH_ASSERT */
66 #define CTRL_REG_SET(reg, val) __builtin_arm_wsr64((reg), (val))
67 #endif /* MACH_ASSERT */
68
69 #pragma mark core counters
70
71 const bool mt_core_supported = true;
72
73 static const ml_topology_info_t *topology_info;
74
75 /*
76 * PMC[0-1] are the 48/64-bit fixed counters -- PMC0 is cycles and PMC1 is
77 * instructions (see arm64/monotonic.h).
78 *
79 * PMC2+ are currently handled by kpc.
80 */
81 #define PMC_0_7(X, A) X(0, A); X(1, A); X(2, A); X(3, A); X(4, A); X(5, A); \
82 X(6, A); X(7, A)
83
84 #if CORE_NCTRS > 8
85 #define PMC_8_9(X, A) X(8, A); X(9, A)
86 #else // CORE_NCTRS > 8
87 #define PMC_8_9(X, A)
88 #endif // CORE_NCTRS > 8
89
90 #define PMC_ALL(X, A) PMC_0_7(X, A); PMC_8_9(X, A)
91
92 #if CPMU_64BIT_PMCS
93 #define PMC_WIDTH (63)
94 #else // UPMU_64BIT_PMCS
95 #define PMC_WIDTH (47)
96 #endif // !UPMU_64BIT_PMCS
97
98 #define CTR_MAX ((UINT64_C(1) << PMC_WIDTH) - 1)
99
100 #define CYCLES 0
101 #define INSTRS 1
102
103 /*
104 * PMC0's offset into a core's PIO range.
105 *
106 * This allows cores to remotely query another core's counters.
107 */
108
109 #define PIO_PMC0_OFFSET (0x200)
110
111 /*
112 * The offset of the counter in the configuration registers. Post-Hurricane
113 * devices have additional counters that need a larger shift than the original
114 * counters.
115 *
116 * XXX For now, just support the lower-numbered counters.
117 */
118 #define CTR_POS(CTR) (CTR)
119
120 /*
121 * PMCR0 is the main control register for the performance monitor. It
122 * controls whether the counters are enabled, how they deliver interrupts, and
123 * other features.
124 */
125
126 #define PMCR0_CTR_EN(CTR) (UINT64_C(1) << CTR_POS(CTR))
127 #define PMCR0_FIXED_EN (PMCR0_CTR_EN(CYCLES) | PMCR0_CTR_EN(INSTRS))
128 /* how interrupts are delivered on a PMI */
129 enum {
130 PMCR0_INTGEN_OFF = 0,
131 PMCR0_INTGEN_PMI = 1,
132 PMCR0_INTGEN_AIC = 2,
133 PMCR0_INTGEN_HALT = 3,
134 PMCR0_INTGEN_FIQ = 4,
135 };
136 #define PMCR0_INTGEN_SET(X) ((uint64_t)(X) << 8)
137
138 #if CPMU_AIC_PMI
139 #define PMCR0_INTGEN_INIT PMCR0_INTGEN_SET(PMCR0_INTGEN_AIC)
140 #else /* CPMU_AIC_PMI */
141 #define PMCR0_INTGEN_INIT PMCR0_INTGEN_SET(PMCR0_INTGEN_FIQ)
142 #endif /* !CPMU_AIC_PMI */
143
144 #define PMCR0_PMI_SHIFT (12)
145 #define PMCR0_CTR_GE8_PMI_SHIFT (44)
146 #define PMCR0_PMI_EN(CTR) (UINT64_C(1) << (PMCR0_PMI_SHIFT + CTR_POS(CTR)))
147 /* fixed counters are always counting */
148 #define PMCR0_PMI_INIT (PMCR0_PMI_EN(CYCLES) | PMCR0_PMI_EN(INSTRS))
149 /* disable counting on a PMI */
150 #define PMCR0_DISCNT_EN (UINT64_C(1) << 20)
151 /* block PMIs until ERET retires */
152 #define PMCR0_WFRFE_EN (UINT64_C(1) << 22)
153 /* count global (not just core-local) L2C events */
154 #define PMCR0_L2CGLOBAL_EN (UINT64_C(1) << 23)
155 /* user mode access to configuration registers */
156 #define PMCR0_USEREN_EN (UINT64_C(1) << 30)
157 #define PMCR0_CTR_GE8_EN_SHIFT (32)
158
159 #if HAS_CPMU_PC_CAPTURE
160 #define PMCR0_PCC_INIT (UINT64_C(0x7) << 24)
161 #else /* HAS_CPMU_PC_CAPTURE */
162 #define PMCR0_PCC_INIT (0)
163 #endif /* !HAS_CPMU_PC_CAPTURE */
164
165 #define PMCR0_INIT (PMCR0_INTGEN_INIT | PMCR0_PMI_INIT | PMCR0_PCC_INIT)
166
167 /*
168 * PMCR1 controls which execution modes count events.
169 */
170 #define PMCR1_EL0A32_EN(CTR) (UINT64_C(1) << (0 + CTR_POS(CTR)))
171 #define PMCR1_EL0A64_EN(CTR) (UINT64_C(1) << (8 + CTR_POS(CTR)))
172 #define PMCR1_EL1A64_EN(CTR) (UINT64_C(1) << (16 + CTR_POS(CTR)))
173 /* PMCR1_EL3A64 is not supported on systems with no monitor */
174 #if defined(APPLEHURRICANE)
175 #define PMCR1_EL3A64_EN(CTR) UINT64_C(0)
176 #else
177 #define PMCR1_EL3A64_EN(CTR) (UINT64_C(1) << (24 + CTR_POS(CTR)))
178 #endif
179 #define PMCR1_ALL_EN(CTR) (PMCR1_EL0A32_EN(CTR) | PMCR1_EL0A64_EN(CTR) | \
180 PMCR1_EL1A64_EN(CTR) | PMCR1_EL3A64_EN(CTR))
181
182 /* fixed counters always count in all modes */
183 #define PMCR1_INIT (PMCR1_ALL_EN(CYCLES) | PMCR1_ALL_EN(INSTRS))
184
185 static inline void
core_init_execution_modes(void)186 core_init_execution_modes(void)
187 {
188 uint64_t pmcr1;
189
190 pmcr1 = __builtin_arm_rsr64("PMCR1_EL1");
191 pmcr1 |= PMCR1_INIT;
192 __builtin_arm_wsr64("PMCR1_EL1", pmcr1);
193 }
194
195 #define PMSR_OVF(CTR) (1ULL << (CTR))
196
197 static int
core_init(__unused mt_device_t dev)198 core_init(__unused mt_device_t dev)
199 {
200 /* the dev node interface to the core counters is still unsupported */
201 return ENOTSUP;
202 }
203
204 struct mt_cpu *
mt_cur_cpu(void)205 mt_cur_cpu(void)
206 {
207 return &getCpuDatap()->cpu_monotonic;
208 }
209
210 uint64_t
mt_core_snap(unsigned int ctr)211 mt_core_snap(unsigned int ctr)
212 {
213 switch (ctr) {
214 #define PMC_RD(CTR, UNUSED) case (CTR): return __builtin_arm_rsr64(__MSR_STR(PMC ## CTR))
215 PMC_ALL(PMC_RD, 0);
216 #undef PMC_RD
217 default:
218 panic("monotonic: invalid core counter read: %u", ctr);
219 __builtin_unreachable();
220 }
221 }
222
223 void
mt_core_set_snap(unsigned int ctr,uint64_t count)224 mt_core_set_snap(unsigned int ctr, uint64_t count)
225 {
226 switch (ctr) {
227 case 0:
228 __builtin_arm_wsr64("PMC0", count);
229 break;
230 case 1:
231 __builtin_arm_wsr64("PMC1", count);
232 break;
233 default:
234 panic("monotonic: invalid core counter %u write %llu", ctr, count);
235 __builtin_unreachable();
236 }
237 }
238
239 static void
core_set_enabled(void)240 core_set_enabled(void)
241 {
242 uint32_t kpc_mask = kpc_get_running() &
243 (KPC_CLASS_CONFIGURABLE_MASK | KPC_CLASS_POWER_MASK);
244 uint64_t pmcr0 = __builtin_arm_rsr64("PMCR0_EL1");
245 pmcr0 |= PMCR0_INIT | PMCR0_FIXED_EN;
246
247 if (kpc_mask != 0) {
248 uint64_t kpc_ctrs = kpc_get_configurable_pmc_mask(kpc_mask) <<
249 MT_CORE_NFIXED;
250 #if KPC_ARM64_CONFIGURABLE_COUNT > 6
251 uint64_t ctrs_ge8 = kpc_ctrs >> 8;
252 pmcr0 |= ctrs_ge8 << PMCR0_CTR_GE8_EN_SHIFT;
253 pmcr0 |= ctrs_ge8 << PMCR0_CTR_GE8_PMI_SHIFT;
254 kpc_ctrs &= (1ULL << 8) - 1;
255 #endif /* KPC_ARM64_CONFIGURABLE_COUNT > 6 */
256 kpc_ctrs |= kpc_ctrs << PMCR0_PMI_SHIFT;
257 pmcr0 |= kpc_ctrs;
258 }
259
260 __builtin_arm_wsr64("PMCR0_EL1", pmcr0);
261 #if MACH_ASSERT
262 /*
263 * Only check for the values that were ORed in.
264 */
265 uint64_t pmcr0_check = __builtin_arm_rsr64("PMCR0_EL1");
266 if ((pmcr0_check & (PMCR0_INIT | PMCR0_FIXED_EN)) != (PMCR0_INIT | PMCR0_FIXED_EN)) {
267 panic("monotonic: hardware ignored enable (read %llx, wrote %llx)",
268 pmcr0_check, pmcr0);
269 }
270 #endif /* MACH_ASSERT */
271 }
272
273 static void
core_idle(__unused cpu_data_t * cpu)274 core_idle(__unused cpu_data_t *cpu)
275 {
276 assert(cpu != NULL);
277 assert(ml_get_interrupts_enabled() == FALSE);
278
279 #if DEBUG
280 uint64_t pmcr0 = __builtin_arm_rsr64("PMCR0_EL1");
281 if ((pmcr0 & PMCR0_FIXED_EN) == 0) {
282 panic("monotonic: counters disabled before idling, pmcr0 = 0x%llx", pmcr0);
283 }
284 uint64_t pmcr1 = __builtin_arm_rsr64("PMCR1_EL1");
285 if ((pmcr1 & PMCR1_INIT) == 0) {
286 panic("monotonic: counter modes disabled before idling, pmcr1 = 0x%llx", pmcr1);
287 }
288 #endif /* DEBUG */
289
290 /* disable counters before updating */
291 __builtin_arm_wsr64("PMCR0_EL1", PMCR0_INIT);
292
293 mt_update_fixed_counts();
294 }
295
296 #pragma mark uncore performance monitor
297
298 #if HAS_UNCORE_CTRS
299
300 static bool mt_uncore_initted = false;
301
302 /*
303 * Uncore Performance Monitor
304 *
305 * Uncore performance monitors provide event-counting for the last-level caches
306 * (LLCs). Each LLC has its own uncore performance monitor, which can only be
307 * accessed by cores that use that LLC. Like the core performance monitoring
308 * unit, uncore counters are configured globally. If there is more than one
309 * LLC on the system, PIO reads must be used to satisfy uncore requests (using
310 * the `_r` remote variants of the access functions). Otherwise, local MSRs
311 * suffice (using the `_l` local variants of the access functions).
312 */
313
314 #if UNCORE_PER_CLUSTER
315 #define MAX_NMONITORS MAX_CPU_CLUSTERS
316 static uintptr_t cpm_impl[MAX_NMONITORS] = {};
317 #else
318 #define MAX_NMONITORS (1)
319 #endif /* UNCORE_PER_CLUSTER */
320
321 #if UNCORE_VERSION >= 2
322 /*
323 * V2 uncore monitors feature a CTI mechanism -- the second bit of UPMSR is
324 * used to track if a CTI has been triggered due to an overflow.
325 */
326 #define UPMSR_OVF_POS 2
327 #else /* UNCORE_VERSION >= 2 */
328 #define UPMSR_OVF_POS 1
329 #endif /* UNCORE_VERSION < 2 */
330 #define UPMSR_OVF(R, CTR) ((R) >> ((CTR) + UPMSR_OVF_POS) & 0x1)
331 #define UPMSR_OVF_MASK (((UINT64_C(1) << UNCORE_NCTRS) - 1) << UPMSR_OVF_POS)
332
333 #define UPMPCM_CORE(ID) (UINT64_C(1) << (ID))
334
335 #if UPMU_64BIT_PMCS
336 #define UPMC_WIDTH (63)
337 #else // UPMU_64BIT_PMCS
338 #define UPMC_WIDTH (47)
339 #endif // !UPMU_64BIT_PMCS
340
341 /*
342 * The uncore_pmi_mask is a bitmask of CPUs that receive uncore PMIs. It's
343 * initialized by uncore_init and controllable by the uncore_pmi_mask boot-arg.
344 */
345 static int32_t uncore_pmi_mask = 0;
346
347 /*
348 * The uncore_active_ctrs is a bitmask of uncore counters that are currently
349 * requested.
350 */
351 static uint16_t uncore_active_ctrs = 0;
352 static_assert(sizeof(uncore_active_ctrs) * CHAR_BIT >= UNCORE_NCTRS,
353 "counter mask should fit the full range of counters");
354
355 /*
356 * mt_uncore_enabled is true when any uncore counters are active.
357 */
358 bool mt_uncore_enabled = false;
359
360 /*
361 * The uncore_events are the event configurations for each uncore counter -- as
362 * a union to make it easy to program the hardware registers.
363 */
364 static struct uncore_config {
365 union {
366 uint8_t uce_ctrs[UNCORE_NCTRS];
367 uint64_t uce_regs[UNCORE_NCTRS / 8];
368 } uc_events;
369 union {
370 uint16_t uccm_masks[UNCORE_NCTRS];
371 uint64_t uccm_regs[UNCORE_NCTRS / 4];
372 } uc_cpu_masks[MAX_NMONITORS];
373 } uncore_config;
374
375 static struct uncore_monitor {
376 /*
377 * The last snapshot of each of the hardware counter values.
378 */
379 uint64_t um_snaps[UNCORE_NCTRS];
380
381 /*
382 * The accumulated counts for each counter.
383 */
384 uint64_t um_counts[UNCORE_NCTRS];
385
386 /*
387 * Protects accessing the hardware registers and fields in this structure.
388 */
389 lck_spin_t um_lock;
390
391 /*
392 * Whether this monitor needs its registers restored after wake.
393 */
394 bool um_sleeping;
395
396 #if MACH_ASSERT
397 /*
398 * Save the last ID that read from this monitor.
399 */
400 uint8_t um_last_read_id;
401
402 /*
403 * Save whether this monitor has been read since sleeping.
404 */
405 bool um_read_since_sleep;
406 #endif /* MACH_ASSERT */
407 } uncore_monitors[MAX_NMONITORS];
408
409 /*
410 * Each uncore unit has its own monitor, corresponding to the memory hierarchy
411 * of the LLCs.
412 */
413 static unsigned int
uncore_nmonitors(void)414 uncore_nmonitors(void)
415 {
416 #if UNCORE_PER_CLUSTER
417 return topology_info->num_clusters;
418 #else /* UNCORE_PER_CLUSTER */
419 return 1;
420 #endif /* !UNCORE_PER_CLUSTER */
421 }
422
423 static unsigned int
uncmon_get_curid(void)424 uncmon_get_curid(void)
425 {
426 #if UNCORE_PER_CLUSTER
427 return cpu_cluster_id();
428 #else /* UNCORE_PER_CLUSTER */
429 return 0;
430 #endif /* !UNCORE_PER_CLUSTER */
431 }
432
433 /*
434 * Per-monitor locks are required to prevent races with the PMI handlers, not
435 * from other CPUs that are configuring (those are serialized with monotonic's
436 * per-device lock).
437 */
438
439 static int
uncmon_lock(struct uncore_monitor * mon)440 uncmon_lock(struct uncore_monitor *mon)
441 {
442 int intrs_en = ml_set_interrupts_enabled(FALSE);
443 lck_spin_lock(&mon->um_lock);
444 return intrs_en;
445 }
446
447 static void
uncmon_unlock(struct uncore_monitor * mon,int intrs_en)448 uncmon_unlock(struct uncore_monitor *mon, int intrs_en)
449 {
450 lck_spin_unlock(&mon->um_lock);
451 (void)ml_set_interrupts_enabled(intrs_en);
452 }
453
454 /*
455 * Helper functions for accessing the hardware -- these require the monitor be
456 * locked to prevent other CPUs' PMI handlers from making local modifications
457 * or updating the counts.
458 */
459
460 #if UNCORE_VERSION >= 2
461 #define UPMCR0_INTEN_POS 20
462 #define UPMCR0_INTGEN_POS 16
463 #else /* UNCORE_VERSION >= 2 */
464 #define UPMCR0_INTEN_POS 12
465 #define UPMCR0_INTGEN_POS 8
466 #endif /* UNCORE_VERSION < 2 */
467 enum {
468 UPMCR0_INTGEN_OFF = 0,
469 /* fast PMIs are only supported on core CPMU */
470 UPMCR0_INTGEN_AIC = 2,
471 UPMCR0_INTGEN_HALT = 3,
472 UPMCR0_INTGEN_FIQ = 4,
473 };
474 /* always enable interrupts for all counters */
475 #define UPMCR0_INTEN (((1ULL << UNCORE_NCTRS) - 1) << UPMCR0_INTEN_POS)
476 /* route uncore PMIs through the FIQ path */
477 #define UPMCR0_INIT (UPMCR0_INTEN | (UPMCR0_INTGEN_FIQ << UPMCR0_INTGEN_POS))
478
479 /*
480 * Turn counting on for counters set in the `enctrmask` and off, otherwise.
481 */
482 static inline void
uncmon_set_counting_locked_l(__unused unsigned int monid,uint64_t enctrmask)483 uncmon_set_counting_locked_l(__unused unsigned int monid, uint64_t enctrmask)
484 {
485 /*
486 * UPMCR0 controls which counters are enabled and how interrupts are generated
487 * for overflows.
488 */
489 __builtin_arm_wsr64("UPMCR0_EL1", UPMCR0_INIT | enctrmask);
490 }
491
492 #if UNCORE_PER_CLUSTER
493
494 /*
495 * Turn counting on for counters set in the `enctrmask` and off, otherwise.
496 */
497 static inline void
uncmon_set_counting_locked_r(unsigned int monid,uint64_t enctrmask)498 uncmon_set_counting_locked_r(unsigned int monid, uint64_t enctrmask)
499 {
500 const uintptr_t upmcr0_offset = 0x4180;
501 *(uint64_t *)(cpm_impl[monid] + upmcr0_offset) = UPMCR0_INIT | enctrmask;
502 }
503
504 #endif /* UNCORE_PER_CLUSTER */
505
506 /*
507 * The uncore performance monitoring counters (UPMCs) are 48/64-bits wide. The
508 * high bit is an overflow bit, triggering a PMI, providing 47/63 usable bits.
509 */
510
511 #define UPMC_MAX ((UINT64_C(1) << UPMC_WIDTH) - 1)
512
513 /*
514 * The `__builtin_arm_{r,w}sr` functions require constant strings, since the
515 * MSR/MRS instructions encode the registers as immediates. Otherwise, this
516 * would be indexing into an array of strings.
517 */
518
519 #define UPMC_0_7(X, A) X(0, A); X(1, A); X(2, A); X(3, A); X(4, A); X(5, A); \
520 X(6, A); X(7, A)
521 #if UNCORE_NCTRS <= 8
522 #define UPMC_ALL(X, A) UPMC_0_7(X, A)
523 #else /* UNCORE_NCTRS <= 8 */
524 #define UPMC_8_15(X, A) X(8, A); X(9, A); X(10, A); X(11, A); X(12, A); \
525 X(13, A); X(14, A); X(15, A)
526 #define UPMC_ALL(X, A) UPMC_0_7(X, A); UPMC_8_15(X, A)
527 #endif /* UNCORE_NCTRS > 8 */
528
529 static inline uint64_t
uncmon_read_counter_locked_l(__unused unsigned int monid,unsigned int ctr)530 uncmon_read_counter_locked_l(__unused unsigned int monid, unsigned int ctr)
531 {
532 assert(ctr < UNCORE_NCTRS);
533 switch (ctr) {
534 #define UPMC_RD(CTR, UNUSED) case (CTR): return __builtin_arm_rsr64(__MSR_STR(UPMC ## CTR))
535 UPMC_ALL(UPMC_RD, 0);
536 #undef UPMC_RD
537 default:
538 panic("monotonic: invalid counter read %u", ctr);
539 __builtin_unreachable();
540 }
541 }
542
543 static inline void
uncmon_write_counter_locked_l(__unused unsigned int monid,unsigned int ctr,uint64_t count)544 uncmon_write_counter_locked_l(__unused unsigned int monid, unsigned int ctr,
545 uint64_t count)
546 {
547 assert(count < UPMC_MAX);
548 assert(ctr < UNCORE_NCTRS);
549 switch (ctr) {
550 #define UPMC_WR(CTR, COUNT) case (CTR): \
551 return __builtin_arm_wsr64(__MSR_STR(UPMC ## CTR), (COUNT))
552 UPMC_ALL(UPMC_WR, count);
553 #undef UPMC_WR
554 default:
555 panic("monotonic: invalid counter write %u", ctr);
556 }
557 }
558
559 #if UNCORE_PER_CLUSTER
560
561 uintptr_t upmc_offs[UNCORE_NCTRS] = {
562 [0] = 0x4100, [1] = 0x4248, [2] = 0x4110, [3] = 0x4250, [4] = 0x4120,
563 [5] = 0x4258, [6] = 0x4130, [7] = 0x4260, [8] = 0x4140, [9] = 0x4268,
564 [10] = 0x4150, [11] = 0x4270, [12] = 0x4160, [13] = 0x4278,
565 [14] = 0x4170, [15] = 0x4280,
566 };
567
568 static inline uint64_t
uncmon_read_counter_locked_r(unsigned int mon_id,unsigned int ctr)569 uncmon_read_counter_locked_r(unsigned int mon_id, unsigned int ctr)
570 {
571 assert(mon_id < uncore_nmonitors());
572 assert(ctr < UNCORE_NCTRS);
573 return *(uint64_t *)(cpm_impl[mon_id] + upmc_offs[ctr]);
574 }
575
576 static inline void
uncmon_write_counter_locked_r(unsigned int mon_id,unsigned int ctr,uint64_t count)577 uncmon_write_counter_locked_r(unsigned int mon_id, unsigned int ctr,
578 uint64_t count)
579 {
580 assert(count < UPMC_MAX);
581 assert(ctr < UNCORE_NCTRS);
582 assert(mon_id < uncore_nmonitors());
583 *(uint64_t *)(cpm_impl[mon_id] + upmc_offs[ctr]) = count;
584 }
585
586 #endif /* UNCORE_PER_CLUSTER */
587
588 static inline void
uncmon_update_locked(unsigned int monid,unsigned int curid,unsigned int ctr)589 uncmon_update_locked(unsigned int monid, unsigned int curid, unsigned int ctr)
590 {
591 struct uncore_monitor *mon = &uncore_monitors[monid];
592 if (!mon->um_sleeping) {
593 uint64_t snap = 0;
594 if (curid == monid) {
595 snap = uncmon_read_counter_locked_l(monid, ctr);
596 } else {
597 #if UNCORE_PER_CLUSTER
598 snap = uncmon_read_counter_locked_r(monid, ctr);
599 #endif /* UNCORE_PER_CLUSTER */
600 }
601 if (snap < mon->um_snaps[ctr]) {
602 #if MACH_ASSERT
603 #if UNCORE_PER_CLUSTER
604 uint64_t remote_value = uncmon_read_counter_locked_r(monid, ctr);
605 #endif /* UNCORE_PER_CLUSTER */
606 panic("monotonic: UPMC%d on UPMU %d went backwards from "
607 "%llx to %llx, read via %s, last was %s from UPMU %hhd%s"
608 #if UNCORE_PER_CLUSTER
609 ", re-read remote value is %llx"
610 #endif /* UNCORE_PER_CLUSTER */
611 , ctr,
612 monid, mon->um_snaps[ctr], snap,
613 curid == monid ? "local" : "remote",
614 mon->um_last_read_id == monid ? "local" : "remote",
615 mon->um_last_read_id,
616 mon->um_read_since_sleep ? "" : ", first read since sleep"
617 #if UNCORE_PER_CLUSTER
618 , remote_value
619 #endif /* UNCORE_PER_CLUSTER */
620 );
621 #else /* MACH_ASSERT */
622 snap = mon->um_snaps[ctr];
623 #endif /* !MACH_ASSERT */
624 }
625 mon->um_counts[ctr] += snap - mon->um_snaps[ctr];
626 mon->um_snaps[ctr] = snap;
627 }
628 }
629
630 static inline void
uncmon_program_events_locked_l(unsigned int monid)631 uncmon_program_events_locked_l(unsigned int monid)
632 {
633 /*
634 * UPMESR[01] is the event selection register that determines which event a
635 * counter will count.
636 */
637 CTRL_REG_SET("UPMESR0_EL1", uncore_config.uc_events.uce_regs[0]);
638
639 #if UNCORE_NCTRS > 8
640 CTRL_REG_SET("UPMESR1_EL1", uncore_config.uc_events.uce_regs[1]);
641 #endif /* UNCORE_NCTRS > 8 */
642
643 /*
644 * UPMECM[0123] are the event core masks for each counter -- whether or not
645 * that counter counts events generated by an agent. These are set to all
646 * ones so the uncore counters count events from all cores.
647 *
648 * The bits are based off the start of the cluster -- e.g. even if a core
649 * has a CPU ID of 4, it might be the first CPU in a cluster. Shift the
650 * registers right by the ID of the first CPU in the cluster.
651 */
652 CTRL_REG_SET("UPMECM0_EL1",
653 uncore_config.uc_cpu_masks[monid].uccm_regs[0]);
654 CTRL_REG_SET("UPMECM1_EL1",
655 uncore_config.uc_cpu_masks[monid].uccm_regs[1]);
656
657 #if UNCORE_NCTRS > 8
658 CTRL_REG_SET("UPMECM2_EL1",
659 uncore_config.uc_cpu_masks[monid].uccm_regs[2]);
660 CTRL_REG_SET("UPMECM3_EL1",
661 uncore_config.uc_cpu_masks[monid].uccm_regs[3]);
662 #endif /* UNCORE_NCTRS > 8 */
663 }
664
665 #if UNCORE_PER_CLUSTER
666
667 static inline void
uncmon_program_events_locked_r(unsigned int monid)668 uncmon_program_events_locked_r(unsigned int monid)
669 {
670 const uintptr_t upmesr_offs[2] = {[0] = 0x41b0, [1] = 0x41b8, };
671
672 for (unsigned int i = 0; i < sizeof(upmesr_offs) / sizeof(upmesr_offs[0]);
673 i++) {
674 *(uint64_t *)(cpm_impl[monid] + upmesr_offs[i]) =
675 uncore_config.uc_events.uce_regs[i];
676 }
677
678 const uintptr_t upmecm_offs[4] = {
679 [0] = 0x4190, [1] = 0x4198, [2] = 0x41a0, [3] = 0x41a8,
680 };
681
682 for (unsigned int i = 0; i < sizeof(upmecm_offs) / sizeof(upmecm_offs[0]);
683 i++) {
684 *(uint64_t *)(cpm_impl[monid] + upmecm_offs[i]) =
685 uncore_config.uc_cpu_masks[monid].uccm_regs[i];
686 }
687 }
688
689 #endif /* UNCORE_PER_CLUSTER */
690
691 static void
uncmon_clear_int_locked_l(__unused unsigned int monid)692 uncmon_clear_int_locked_l(__unused unsigned int monid)
693 {
694 __builtin_arm_wsr64("UPMSR_EL1", 0);
695 }
696
697 #if UNCORE_PER_CLUSTER
698
699 static void
uncmon_clear_int_locked_r(unsigned int monid)700 uncmon_clear_int_locked_r(unsigned int monid)
701 {
702 const uintptr_t upmsr_off = 0x41c0;
703 *(uint64_t *)(cpm_impl[monid] + upmsr_off) = 0;
704 }
705
706 #endif /* UNCORE_PER_CLUSTER */
707
708 /*
709 * Get the PMI mask for the provided `monid` -- that is, the bitmap of CPUs
710 * that should be sent PMIs for a particular monitor.
711 */
712 static uint64_t
uncmon_get_pmi_mask(unsigned int monid)713 uncmon_get_pmi_mask(unsigned int monid)
714 {
715 uint64_t pmi_mask = uncore_pmi_mask;
716
717 #if UNCORE_PER_CLUSTER
718 pmi_mask &= topology_info->clusters[monid].cpu_mask;
719 #else /* UNCORE_PER_CLUSTER */
720 #pragma unused(monid)
721 #endif /* !UNCORE_PER_CLUSTER */
722
723 return pmi_mask;
724 }
725
726 /*
727 * Initialization routines for the uncore counters.
728 */
729
730 static void
uncmon_init_locked_l(unsigned int monid)731 uncmon_init_locked_l(unsigned int monid)
732 {
733 /*
734 * UPMPCM defines the PMI core mask for the UPMCs -- which cores should
735 * receive interrupts on overflow.
736 */
737 CTRL_REG_SET("UPMPCM_EL1", uncmon_get_pmi_mask(monid));
738 uncmon_set_counting_locked_l(monid,
739 mt_uncore_enabled ? uncore_active_ctrs : 0);
740 }
741
742 #if UNCORE_PER_CLUSTER
743
744 static uintptr_t acc_impl[MAX_NMONITORS] = {};
745
746 static void
uncmon_init_locked_r(unsigned int monid)747 uncmon_init_locked_r(unsigned int monid)
748 {
749 const uintptr_t upmpcm_off = 0x1010;
750
751 *(uint64_t *)(acc_impl[monid] + upmpcm_off) = uncmon_get_pmi_mask(monid);
752 uncmon_set_counting_locked_r(monid,
753 mt_uncore_enabled ? uncore_active_ctrs : 0);
754 }
755
756 #endif /* UNCORE_PER_CLUSTER */
757
758 /*
759 * Initialize the uncore device for monotonic.
760 */
761 static int
uncore_init(__unused mt_device_t dev)762 uncore_init(__unused mt_device_t dev)
763 {
764 #if HAS_UNCORE_CTRS
765 assert(MT_NDEVS > 0);
766 mt_devices[MT_NDEVS - 1].mtd_nmonitors = (uint8_t)uncore_nmonitors();
767 #endif
768
769 #if DEVELOPMENT || DEBUG
770 /*
771 * Development and debug kernels observe the `uncore_pmi_mask` boot-arg,
772 * allowing PMIs to be routed to the CPUs present in the supplied bitmap.
773 * Do some sanity checks on the value provided.
774 */
775 bool parsed_arg = PE_parse_boot_argn("uncore_pmi_mask", &uncore_pmi_mask,
776 sizeof(uncore_pmi_mask));
777 if (parsed_arg) {
778 #if UNCORE_PER_CLUSTER
779 if (__builtin_popcount(uncore_pmi_mask) != (int)uncore_nmonitors()) {
780 panic("monotonic: invalid uncore PMI mask 0x%x", uncore_pmi_mask);
781 }
782 for (unsigned int i = 0; i < uncore_nmonitors(); i++) {
783 if (__builtin_popcountll(uncmon_get_pmi_mask(i)) != 1) {
784 panic("monotonic: invalid uncore PMI CPU for cluster %d in mask 0x%x",
785 i, uncore_pmi_mask);
786 }
787 }
788 #else /* UNCORE_PER_CLUSTER */
789 if (__builtin_popcount(uncore_pmi_mask) != 1) {
790 panic("monotonic: invalid uncore PMI mask 0x%x", uncore_pmi_mask);
791 }
792 #endif /* !UNCORE_PER_CLUSTER */
793 } else
794 #endif /* DEVELOPMENT || DEBUG */
795 {
796 /* arbitrarily route to core 0 in each cluster */
797 uncore_pmi_mask |= 1;
798 }
799 assert(uncore_pmi_mask != 0);
800
801 for (unsigned int monid = 0; monid < uncore_nmonitors(); monid++) {
802 #if UNCORE_PER_CLUSTER
803 ml_topology_cluster_t *cluster = &topology_info->clusters[monid];
804 cpm_impl[monid] = (uintptr_t)cluster->cpm_IMPL_regs;
805 acc_impl[monid] = (uintptr_t)cluster->acc_IMPL_regs;
806 assert(cpm_impl[monid] != 0 && acc_impl[monid] != 0);
807 #endif /* UNCORE_PER_CLUSTER */
808
809 struct uncore_monitor *mon = &uncore_monitors[monid];
810 lck_spin_init(&mon->um_lock, &mt_lock_grp, LCK_ATTR_NULL);
811 }
812
813 mt_uncore_initted = true;
814
815 return 0;
816 }
817
818 /*
819 * Support for monotonic's mtd_read function.
820 */
821
822 static void
uncmon_read_all_counters(unsigned int monid,unsigned int curmonid,uint64_t ctr_mask,uint64_t * counts)823 uncmon_read_all_counters(unsigned int monid, unsigned int curmonid,
824 uint64_t ctr_mask, uint64_t *counts)
825 {
826 struct uncore_monitor *mon = &uncore_monitors[monid];
827
828 int intrs_en = uncmon_lock(mon);
829
830 for (unsigned int ctr = 0; ctr < UNCORE_NCTRS; ctr++) {
831 if (ctr_mask & (1ULL << ctr)) {
832 if (!mon->um_sleeping) {
833 uncmon_update_locked(monid, curmonid, ctr);
834 }
835 counts[ctr] = mon->um_counts[ctr];
836 }
837 }
838 #if MACH_ASSERT
839 mon->um_read_since_sleep = true;
840 #endif /* MACH_ASSERT */
841
842 uncmon_unlock(mon, intrs_en);
843 }
844
845 /*
846 * Read all monitor's counters.
847 */
848 static int
uncore_read(uint64_t ctr_mask,uint64_t * counts_out)849 uncore_read(uint64_t ctr_mask, uint64_t *counts_out)
850 {
851 assert(ctr_mask != 0);
852 assert(counts_out != NULL);
853
854 if (!uncore_active_ctrs) {
855 return EPWROFF;
856 }
857 if (ctr_mask & ~uncore_active_ctrs) {
858 return EINVAL;
859 }
860
861 unsigned int curmonid = uncmon_get_curid();
862 for (unsigned int monid = 0; monid < uncore_nmonitors(); monid++) {
863 /*
864 * Find this monitor's starting offset into the `counts_out` array.
865 */
866 uint64_t *counts = counts_out + (UNCORE_NCTRS * monid);
867 uncmon_read_all_counters(monid, curmonid, ctr_mask, counts);
868 }
869
870 return 0;
871 }
872
873 /*
874 * Support for monotonic's mtd_add function.
875 */
876
877 /*
878 * Add an event to the current uncore configuration. This doesn't take effect
879 * until the counters are enabled again, so there's no need to involve the
880 * monitors.
881 */
882 static int
uncore_add(struct monotonic_config * config,uint32_t * ctr_out)883 uncore_add(struct monotonic_config *config, uint32_t *ctr_out)
884 {
885 if (mt_uncore_enabled) {
886 return EBUSY;
887 }
888
889 uint32_t available = ~uncore_active_ctrs & config->allowed_ctr_mask;
890
891 if (available == 0) {
892 return ENOSPC;
893 }
894
895 uint32_t valid_ctrs = (UINT32_C(1) << UNCORE_NCTRS) - 1;
896 if ((available & valid_ctrs) == 0) {
897 return E2BIG;
898 }
899 /*
900 * Clear the UPMCs the first time an event is added.
901 */
902 unsigned int curmonid = uncmon_get_curid();
903 if (uncore_active_ctrs == 0) {
904 /*
905 * Suspend powerdown until the next reset.
906 */
907 suspend_cluster_powerdown();
908
909 for (unsigned int monid = 0; monid < uncore_nmonitors(); monid++) {
910 struct uncore_monitor *mon = &uncore_monitors[monid];
911 bool remote = monid != curmonid;
912
913 int intrs_en = uncmon_lock(mon);
914 if (!mon->um_sleeping) {
915 for (unsigned int ctr = 0; ctr < UNCORE_NCTRS; ctr++) {
916 if (remote) {
917 #if UNCORE_PER_CLUSTER
918 uncmon_write_counter_locked_r(monid, ctr, 0);
919 #endif /* UNCORE_PER_CLUSTER */
920 } else {
921 uncmon_write_counter_locked_l(monid, ctr, 0);
922 }
923 }
924 }
925 memset(&mon->um_snaps, 0, sizeof(mon->um_snaps));
926 memset(&mon->um_counts, 0, sizeof(mon->um_counts));
927 uncmon_unlock(mon, intrs_en);
928 }
929 }
930
931 uint32_t ctr = __builtin_ffsll(available) - 1;
932
933 uncore_active_ctrs |= UINT64_C(1) << ctr;
934 uncore_config.uc_events.uce_ctrs[ctr] = (uint8_t)config->event;
935 uint64_t cpu_mask = UINT64_MAX;
936 if (config->cpu_mask != 0) {
937 cpu_mask = config->cpu_mask;
938 }
939 for (unsigned int i = 0; i < uncore_nmonitors(); i++) {
940 #if UNCORE_PER_CLUSTER
941 const unsigned int shift = topology_info->clusters[i].first_cpu_id;
942 #else /* UNCORE_PER_CLUSTER */
943 const unsigned int shift = 0;
944 #endif /* !UNCORE_PER_CLUSTER */
945 uncore_config.uc_cpu_masks[i].uccm_masks[ctr] = (uint16_t)(cpu_mask >> shift);
946 }
947
948 *ctr_out = ctr;
949 return 0;
950 }
951
952 /*
953 * Support for monotonic's mtd_reset function.
954 */
955
956 /*
957 * Reset all configuration and disable the counters if they're currently
958 * counting.
959 */
960 static void
uncore_reset(void)961 uncore_reset(void)
962 {
963 mt_uncore_enabled = false;
964
965 unsigned int curmonid = uncmon_get_curid();
966
967 if (mt_owns_counters()) {
968 if (uncore_active_ctrs != 0) {
969 resume_cluster_powerdown();
970 }
971
972 for (unsigned int monid = 0; monid < uncore_nmonitors(); monid++) {
973 struct uncore_monitor *mon = &uncore_monitors[monid];
974 bool remote = monid != curmonid;
975
976 int intrs_en = uncmon_lock(mon);
977 if (!mon->um_sleeping) {
978 if (remote) {
979 #if UNCORE_PER_CLUSTER
980 uncmon_set_counting_locked_r(monid, 0);
981 #endif /* UNCORE_PER_CLUSTER */
982 } else {
983 uncmon_set_counting_locked_l(monid, 0);
984 }
985
986 for (int ctr = 0; ctr < UNCORE_NCTRS; ctr++) {
987 if (uncore_active_ctrs & (1U << ctr)) {
988 if (remote) {
989 #if UNCORE_PER_CLUSTER
990 uncmon_write_counter_locked_r(monid, ctr, 0);
991 #endif /* UNCORE_PER_CLUSTER */
992 } else {
993 uncmon_write_counter_locked_l(monid, ctr, 0);
994 }
995 }
996 }
997 }
998
999 memset(&mon->um_snaps, 0, sizeof(mon->um_snaps));
1000 memset(&mon->um_counts, 0, sizeof(mon->um_counts));
1001 if (!mon->um_sleeping) {
1002 if (remote) {
1003 #if UNCORE_PER_CLUSTER
1004 uncmon_clear_int_locked_r(monid);
1005 #endif /* UNCORE_PER_CLUSTER */
1006 } else {
1007 uncmon_clear_int_locked_l(monid);
1008 }
1009 }
1010
1011 uncmon_unlock(mon, intrs_en);
1012 }
1013 }
1014
1015 uncore_active_ctrs = 0;
1016 memset(&uncore_config, 0, sizeof(uncore_config));
1017
1018 if (mt_owns_counters()) {
1019 for (unsigned int monid = 0; monid < uncore_nmonitors(); monid++) {
1020 struct uncore_monitor *mon = &uncore_monitors[monid];
1021 bool remote = monid != curmonid;
1022
1023 int intrs_en = uncmon_lock(mon);
1024 if (!mon->um_sleeping) {
1025 if (remote) {
1026 #if UNCORE_PER_CLUSTER
1027 uncmon_program_events_locked_r(monid);
1028 #endif /* UNCORE_PER_CLUSTER */
1029 } else {
1030 uncmon_program_events_locked_l(monid);
1031 }
1032 }
1033 uncmon_unlock(mon, intrs_en);
1034 }
1035 }
1036 }
1037
1038 /*
1039 * Support for monotonic's mtd_enable function.
1040 */
1041
1042 static void
uncmon_set_enabled_l(unsigned int monid,bool enable)1043 uncmon_set_enabled_l(unsigned int monid, bool enable)
1044 {
1045 struct uncore_monitor *mon = &uncore_monitors[monid];
1046 int intrs_en = uncmon_lock(mon);
1047
1048 if (enable) {
1049 uncmon_init_locked_l(monid);
1050 uncmon_program_events_locked_l(monid);
1051 uncmon_set_counting_locked_l(monid, uncore_active_ctrs);
1052 } else {
1053 uncmon_set_counting_locked_l(monid, 0);
1054 }
1055
1056 uncmon_unlock(mon, intrs_en);
1057 }
1058
1059 #if UNCORE_PER_CLUSTER
1060
1061 static void
uncmon_set_enabled_r(unsigned int monid,bool enable)1062 uncmon_set_enabled_r(unsigned int monid, bool enable)
1063 {
1064 struct uncore_monitor *mon = &uncore_monitors[monid];
1065 int intrs_en = uncmon_lock(mon);
1066
1067 if (!mon->um_sleeping) {
1068 if (enable) {
1069 uncmon_init_locked_r(monid);
1070 uncmon_program_events_locked_r(monid);
1071 uncmon_set_counting_locked_r(monid, uncore_active_ctrs);
1072 } else {
1073 uncmon_set_counting_locked_r(monid, 0);
1074 }
1075 }
1076
1077 uncmon_unlock(mon, intrs_en);
1078 }
1079
1080 #endif /* UNCORE_PER_CLUSTER */
1081
1082 static void
uncore_set_enabled(bool enable)1083 uncore_set_enabled(bool enable)
1084 {
1085 mt_uncore_enabled = enable;
1086
1087 unsigned int curmonid = uncmon_get_curid();
1088 for (unsigned int monid = 0; monid < uncore_nmonitors(); monid++) {
1089 if (monid != curmonid) {
1090 #if UNCORE_PER_CLUSTER
1091 uncmon_set_enabled_r(monid, enable);
1092 #endif /* UNCORE_PER_CLUSTER */
1093 } else {
1094 uncmon_set_enabled_l(monid, enable);
1095 }
1096 }
1097 }
1098
1099 /*
1100 * Hooks in the machine layer.
1101 */
1102
1103 static void
uncore_fiq(uint64_t upmsr)1104 uncore_fiq(uint64_t upmsr)
1105 {
1106 /*
1107 * Determine which counters overflowed.
1108 */
1109 uint64_t disable_ctr_mask = (upmsr & UPMSR_OVF_MASK) >> UPMSR_OVF_POS;
1110 /* should not receive interrupts from inactive counters */
1111 assert(!(disable_ctr_mask & ~uncore_active_ctrs));
1112
1113 if (uncore_active_ctrs == 0) {
1114 return;
1115 }
1116
1117 unsigned int monid = uncmon_get_curid();
1118 struct uncore_monitor *mon = &uncore_monitors[monid];
1119
1120 int intrs_en = uncmon_lock(mon);
1121
1122 /*
1123 * Disable any counters that overflowed.
1124 */
1125 uncmon_set_counting_locked_l(monid,
1126 uncore_active_ctrs & ~disable_ctr_mask);
1127
1128 /*
1129 * With the overflowing counters disabled, capture their counts and reset
1130 * the UPMCs and their snapshots to 0.
1131 */
1132 for (unsigned int ctr = 0; ctr < UNCORE_NCTRS; ctr++) {
1133 if (UPMSR_OVF(upmsr, ctr)) {
1134 uncmon_update_locked(monid, monid, ctr);
1135 mon->um_snaps[ctr] = 0;
1136 uncmon_write_counter_locked_l(monid, ctr, 0);
1137 }
1138 }
1139
1140 /*
1141 * Acknowledge the interrupt, now that any overflowed PMCs have been reset.
1142 */
1143 uncmon_clear_int_locked_l(monid);
1144
1145 /*
1146 * Re-enable all active counters.
1147 */
1148 uncmon_set_counting_locked_l(monid, uncore_active_ctrs);
1149
1150 uncmon_unlock(mon, intrs_en);
1151 }
1152
1153 static void
uncore_save(void)1154 uncore_save(void)
1155 {
1156 if (!uncore_active_ctrs) {
1157 return;
1158 }
1159
1160 unsigned int curmonid = uncmon_get_curid();
1161
1162 for (unsigned int monid = 0; monid < uncore_nmonitors(); monid++) {
1163 struct uncore_monitor *mon = &uncore_monitors[monid];
1164 int intrs_en = uncmon_lock(mon);
1165
1166 if (mt_uncore_enabled) {
1167 if (monid != curmonid) {
1168 #if UNCORE_PER_CLUSTER
1169 uncmon_set_counting_locked_r(monid, 0);
1170 #endif /* UNCORE_PER_CLUSTER */
1171 } else {
1172 uncmon_set_counting_locked_l(monid, 0);
1173 }
1174 }
1175
1176 for (unsigned int ctr = 0; ctr < UNCORE_NCTRS; ctr++) {
1177 if (uncore_active_ctrs & (1U << ctr)) {
1178 uncmon_update_locked(monid, curmonid, ctr);
1179 mon->um_snaps[ctr] = 0;
1180 uncmon_write_counter_locked_l(monid, ctr, 0);
1181 }
1182 }
1183
1184 mon->um_sleeping = true;
1185 uncmon_unlock(mon, intrs_en);
1186 }
1187 }
1188
1189 static void
uncore_restore(void)1190 uncore_restore(void)
1191 {
1192 if (!uncore_active_ctrs) {
1193 return;
1194 }
1195 unsigned int curmonid = uncmon_get_curid();
1196
1197 struct uncore_monitor *mon = &uncore_monitors[curmonid];
1198 int intrs_en = uncmon_lock(mon);
1199 if (!mon->um_sleeping) {
1200 goto out;
1201 }
1202
1203 for (unsigned int ctr = 0; ctr < UNCORE_NCTRS; ctr++) {
1204 if (uncore_active_ctrs & (1U << ctr)) {
1205 uncmon_write_counter_locked_l(curmonid, ctr, mon->um_snaps[ctr]);
1206 }
1207 }
1208 uncmon_program_events_locked_l(curmonid);
1209 uncmon_init_locked_l(curmonid);
1210 mon->um_sleeping = false;
1211 #if MACH_ASSERT
1212 mon->um_read_since_sleep = false;
1213 #endif /* MACH_ASSERT */
1214
1215 out:
1216 uncmon_unlock(mon, intrs_en);
1217 }
1218
1219 #endif /* HAS_UNCORE_CTRS */
1220
1221 #pragma mark common hooks
1222
1223 void
mt_early_init(void)1224 mt_early_init(void)
1225 {
1226 topology_info = ml_get_topology_info();
1227 }
1228
1229 void
mt_cpu_idle(cpu_data_t * cpu)1230 mt_cpu_idle(cpu_data_t *cpu)
1231 {
1232 core_idle(cpu);
1233 }
1234
1235 void
mt_cpu_run(cpu_data_t * cpu)1236 mt_cpu_run(cpu_data_t *cpu)
1237 {
1238 struct mt_cpu *mtc;
1239
1240 assert(cpu != NULL);
1241 assert(ml_get_interrupts_enabled() == FALSE);
1242
1243 mtc = &cpu->cpu_monotonic;
1244
1245 for (int i = 0; i < MT_CORE_NFIXED; i++) {
1246 mt_core_set_snap(i, mtc->mtc_snaps[i]);
1247 }
1248
1249 /* re-enable the counters */
1250 core_init_execution_modes();
1251
1252 core_set_enabled();
1253 }
1254
1255 void
mt_cpu_down(cpu_data_t * cpu)1256 mt_cpu_down(cpu_data_t *cpu)
1257 {
1258 mt_cpu_idle(cpu);
1259 }
1260
1261 void
mt_cpu_up(cpu_data_t * cpu)1262 mt_cpu_up(cpu_data_t *cpu)
1263 {
1264 mt_cpu_run(cpu);
1265 }
1266
1267 void
mt_sleep(void)1268 mt_sleep(void)
1269 {
1270 #if HAS_UNCORE_CTRS
1271 uncore_save();
1272 #endif /* HAS_UNCORE_CTRS */
1273 }
1274
1275 void
mt_wake_per_core(void)1276 mt_wake_per_core(void)
1277 {
1278 #if HAS_UNCORE_CTRS
1279 if (mt_uncore_initted) {
1280 uncore_restore();
1281 }
1282 #endif /* HAS_UNCORE_CTRS */
1283 }
1284
1285 uint64_t
mt_count_pmis(void)1286 mt_count_pmis(void)
1287 {
1288 uint64_t npmis = 0;
1289 for (unsigned int i = 0; i < topology_info->num_cpus; i++) {
1290 cpu_data_t *cpu = (cpu_data_t *)CpuDataEntries[topology_info->cpus[i].cpu_id].cpu_data_vaddr;
1291 npmis += cpu->cpu_monotonic.mtc_npmis;
1292 }
1293 return npmis;
1294 }
1295
1296 static void
mt_cpu_pmi(cpu_data_t * cpu,uint64_t pmcr0)1297 mt_cpu_pmi(cpu_data_t *cpu, uint64_t pmcr0)
1298 {
1299 assert(cpu != NULL);
1300 assert(ml_get_interrupts_enabled() == FALSE);
1301
1302 __builtin_arm_wsr64("PMCR0_EL1", PMCR0_INIT);
1303 /*
1304 * Ensure the CPMU has flushed any increments at this point, so PMSR is up
1305 * to date.
1306 */
1307 __builtin_arm_isb(ISB_SY);
1308
1309 cpu->cpu_monotonic.mtc_npmis += 1;
1310 cpu->cpu_stat.pmi_cnt_wake += 1;
1311
1312 #if MONOTONIC_DEBUG
1313 if (!PMCR0_PMI(pmcr0)) {
1314 kprintf("monotonic: mt_cpu_pmi but no PMI (PMCR0 = %#llx)\n",
1315 pmcr0);
1316 }
1317 #else /* MONOTONIC_DEBUG */
1318 #pragma unused(pmcr0)
1319 #endif /* !MONOTONIC_DEBUG */
1320
1321 uint64_t pmsr = __builtin_arm_rsr64("PMSR_EL1");
1322
1323 #if MONOTONIC_DEBUG
1324 printf("monotonic: cpu = %d, PMSR = 0x%llx, PMCR0 = 0x%llx\n",
1325 cpu_number(), pmsr, pmcr0);
1326 #endif /* MONOTONIC_DEBUG */
1327
1328 #if MACH_ASSERT
1329 uint64_t handled = 0;
1330 #endif /* MACH_ASSERT */
1331
1332 /*
1333 * monotonic handles any fixed counter PMIs.
1334 */
1335 for (unsigned int i = 0; i < MT_CORE_NFIXED; i++) {
1336 if ((pmsr & PMSR_OVF(i)) == 0) {
1337 continue;
1338 }
1339
1340 #if MACH_ASSERT
1341 handled |= 1ULL << i;
1342 #endif /* MACH_ASSERT */
1343 uint64_t count = mt_cpu_update_count(cpu, i);
1344 cpu->cpu_monotonic.mtc_counts[i] += count;
1345 mt_core_set_snap(i, mt_core_reset_values[i]);
1346 cpu->cpu_monotonic.mtc_snaps[i] = mt_core_reset_values[i];
1347
1348 if (mt_microstackshots && mt_microstackshot_ctr == i) {
1349 bool user_mode = false;
1350 arm_saved_state_t *state = get_user_regs(current_thread());
1351 if (state) {
1352 user_mode = PSR64_IS_USER(get_saved_state_cpsr(state));
1353 }
1354 KDBG_RELEASE(KDBG_EVENTID(DBG_MONOTONIC, DBG_MT_DEBUG, 1),
1355 mt_microstackshot_ctr, user_mode);
1356 mt_microstackshot_pmi_handler(user_mode, mt_microstackshot_ctx);
1357 } else if (mt_debug) {
1358 KDBG_RELEASE(KDBG_EVENTID(DBG_MONOTONIC, DBG_MT_DEBUG, 2),
1359 i, count);
1360 }
1361 }
1362
1363 /*
1364 * KPC handles the configurable counter PMIs.
1365 */
1366 for (unsigned int i = MT_CORE_NFIXED; i < CORE_NCTRS; i++) {
1367 if (pmsr & PMSR_OVF(i)) {
1368 #if MACH_ASSERT
1369 handled |= 1ULL << i;
1370 #endif /* MACH_ASSERT */
1371 extern void kpc_pmi_handler(unsigned int ctr);
1372 kpc_pmi_handler(i);
1373 }
1374 }
1375
1376 #if MACH_ASSERT
1377 uint64_t pmsr_after_handling = __builtin_arm_rsr64("PMSR_EL1");
1378 if (pmsr_after_handling != 0) {
1379 unsigned int first_ctr_ovf = __builtin_ffsll(pmsr_after_handling) - 1;
1380 uint64_t count = 0;
1381 const char *extra = "";
1382 if (first_ctr_ovf >= CORE_NCTRS) {
1383 extra = " (invalid counter)";
1384 } else {
1385 count = mt_core_snap(first_ctr_ovf);
1386 }
1387
1388 panic("monotonic: PMI status not cleared on exit from handler, "
1389 "PMSR = 0x%llx HANDLE -> -> 0x%llx, handled 0x%llx, "
1390 "PMCR0 = 0x%llx, PMC%d = 0x%llx%s", pmsr, pmsr_after_handling,
1391 handled, __builtin_arm_rsr64("PMCR0_EL1"), first_ctr_ovf, count, extra);
1392 }
1393 #endif /* MACH_ASSERT */
1394
1395 core_set_enabled();
1396 }
1397
1398 #if CPMU_AIC_PMI
1399 void
mt_cpmu_aic_pmi(cpu_id_t source)1400 mt_cpmu_aic_pmi(cpu_id_t source)
1401 {
1402 struct cpu_data *curcpu = getCpuDatap();
1403 if (source != curcpu->interrupt_nub) {
1404 panic("monotonic: PMI from IOCPU %p delivered to %p", source,
1405 curcpu->interrupt_nub);
1406 }
1407 mt_cpu_pmi(curcpu, __builtin_arm_rsr64("PMCR0_EL1"));
1408 }
1409 #endif /* CPMU_AIC_PMI */
1410
1411 void
mt_fiq(void * cpu,uint64_t pmcr0,uint64_t upmsr)1412 mt_fiq(void *cpu, uint64_t pmcr0, uint64_t upmsr)
1413 {
1414 #if CPMU_AIC_PMI
1415 #pragma unused(cpu, pmcr0)
1416 #else /* CPMU_AIC_PMI */
1417 mt_cpu_pmi(cpu, pmcr0);
1418 #endif /* !CPMU_AIC_PMI */
1419
1420 #if HAS_UNCORE_CTRS
1421 if (upmsr != 0) {
1422 uncore_fiq(upmsr);
1423 }
1424 #else /* HAS_UNCORE_CTRS */
1425 #pragma unused(upmsr)
1426 #endif /* !HAS_UNCORE_CTRS */
1427 }
1428
1429 void
mt_ownership_change(bool available)1430 mt_ownership_change(bool available)
1431 {
1432 #if HAS_UNCORE_CTRS
1433 /*
1434 * No need to take the lock here, as this is only manipulated in the UPMU
1435 * when the current task already owns the counters and is on its way out.
1436 */
1437 if (!available && uncore_active_ctrs) {
1438 uncore_reset();
1439 }
1440 #else
1441 #pragma unused(available)
1442 #endif /* HAS_UNCORE_CTRS */
1443 }
1444
1445 static uint32_t mt_xc_sync;
1446
1447 static void
mt_microstackshot_start_remote(__unused void * arg)1448 mt_microstackshot_start_remote(__unused void *arg)
1449 {
1450 cpu_data_t *cpu = getCpuDatap();
1451
1452 __builtin_arm_wsr64("PMCR0_EL1", PMCR0_INIT);
1453
1454 for (int i = 0; i < MT_CORE_NFIXED; i++) {
1455 uint64_t count = mt_cpu_update_count(cpu, i);
1456 cpu->cpu_monotonic.mtc_counts[i] += count;
1457 mt_core_set_snap(i, mt_core_reset_values[i]);
1458 cpu->cpu_monotonic.mtc_snaps[i] = mt_core_reset_values[i];
1459 }
1460
1461 core_set_enabled();
1462
1463 if (os_atomic_dec(&mt_xc_sync, relaxed) == 0) {
1464 thread_wakeup((event_t)&mt_xc_sync);
1465 }
1466 }
1467
1468 int
mt_microstackshot_start_arch(uint64_t period)1469 mt_microstackshot_start_arch(uint64_t period)
1470 {
1471 uint64_t reset_value = 0;
1472 int ovf = os_sub_overflow(CTR_MAX, period, &reset_value);
1473 if (ovf) {
1474 return ERANGE;
1475 }
1476
1477 mt_core_reset_values[mt_microstackshot_ctr] = reset_value;
1478 cpu_broadcast_xcall(&mt_xc_sync, TRUE, mt_microstackshot_start_remote,
1479 mt_microstackshot_start_remote /* cannot pass NULL */);
1480 return 0;
1481 }
1482
1483 #pragma mark dev nodes
1484
1485 struct mt_device mt_devices[] = {
1486 [0] = {
1487 .mtd_name = "core",
1488 .mtd_init = core_init,
1489 },
1490 #if HAS_UNCORE_CTRS
1491 [1] = {
1492 .mtd_name = "uncore",
1493 .mtd_init = uncore_init,
1494 .mtd_add = uncore_add,
1495 .mtd_reset = uncore_reset,
1496 .mtd_enable = uncore_set_enabled,
1497 .mtd_read = uncore_read,
1498
1499 .mtd_ncounters = UNCORE_NCTRS,
1500 }
1501 #endif /* HAS_UNCORE_CTRS */
1502 };
1503
1504 static_assert(
1505 (sizeof(mt_devices) / sizeof(mt_devices[0])) == MT_NDEVS,
1506 "MT_NDEVS macro should be same as the length of mt_devices");
1507