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