xref: /xnu-8796.141.3/osfmk/arm64/monotonic_arm64.c (revision 1b191cb58250d0705d8a51287127505aa4bc0789)
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