xref: /kvm-unit-tests/arm/pmu.c (revision 4ce2a80456240694a72b5b2ba74598cefc6f4d6f)
1 /*
2  * Test the ARM Performance Monitors Unit (PMU).
3  *
4  * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
5  * Copyright (C) 2016, Red Hat Inc, Wei Huang <wei@redhat.com>
6  *
7  * This program is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU Lesser General Public License version 2.1 and
9  * only version 2.1 as published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
14  * for more details.
15  */
16 #include "libcflat.h"
17 #include "errata.h"
18 #include "asm/barrier.h"
19 #include "asm/sysreg.h"
20 #include "asm/processor.h"
21 #include <bitops.h>
22 #include <asm/gic.h>
23 
24 #define PMU_PMCR_E         (1 << 0)
25 #define PMU_PMCR_P         (1 << 1)
26 #define PMU_PMCR_C         (1 << 2)
27 #define PMU_PMCR_D         (1 << 3)
28 #define PMU_PMCR_X         (1 << 4)
29 #define PMU_PMCR_DP        (1 << 5)
30 #define PMU_PMCR_LC        (1 << 6)
31 #define PMU_PMCR_N_SHIFT   11
32 #define PMU_PMCR_N_MASK    0x1f
33 #define PMU_PMCR_ID_SHIFT  16
34 #define PMU_PMCR_ID_MASK   0xff
35 #define PMU_PMCR_IMP_SHIFT 24
36 #define PMU_PMCR_IMP_MASK  0xff
37 
38 #define PMU_CYCLE_IDX      31
39 
40 #define NR_SAMPLES 10
41 
42 /* Some PMU events */
43 #define SW_INCR			0x0
44 #define INST_RETIRED		0x8
45 #define CPU_CYCLES		0x11
46 #define MEM_ACCESS		0x13
47 #define INST_PREC		0x1B
48 #define STALL_FRONTEND		0x23
49 #define STALL_BACKEND		0x24
50 
51 #define COMMON_EVENTS_LOW	0x0
52 #define COMMON_EVENTS_HIGH	0x3F
53 #define EXT_COMMON_EVENTS_LOW	0x4000
54 #define EXT_COMMON_EVENTS_HIGH	0x403F
55 
56 #define ALL_SET			0xFFFFFFFF
57 #define ALL_CLEAR		0x0
58 #define PRE_OVERFLOW		0xFFFFFFF0
59 
60 struct pmu {
61 	unsigned int version;
62 	unsigned int nb_implemented_counters;
63 	uint32_t pmcr_ro;
64 };
65 
66 static struct pmu pmu;
67 
68 #if defined(__arm__)
69 #define ID_DFR0_PERFMON_SHIFT 24
70 #define ID_DFR0_PERFMON_MASK  0xf
71 
72 #define ID_DFR0_PMU_NOTIMPL	0b0000
73 #define ID_DFR0_PMU_V1		0b0001
74 #define ID_DFR0_PMU_V2		0b0010
75 #define ID_DFR0_PMU_V3		0b0011
76 #define ID_DFR0_PMU_V3_8_1	0b0100
77 #define ID_DFR0_PMU_V3_8_4	0b0101
78 #define ID_DFR0_PMU_V3_8_5	0b0110
79 #define ID_DFR0_PMU_IMPDEF	0b1111
80 
81 #define PMCR         __ACCESS_CP15(c9, 0, c12, 0)
82 #define ID_DFR0      __ACCESS_CP15(c0, 0, c1, 2)
83 #define PMSELR       __ACCESS_CP15(c9, 0, c12, 5)
84 #define PMXEVTYPER   __ACCESS_CP15(c9, 0, c13, 1)
85 #define PMCNTENSET   __ACCESS_CP15(c9, 0, c12, 1)
86 #define PMCCNTR32    __ACCESS_CP15(c9, 0, c13, 0)
87 #define PMCCNTR64    __ACCESS_CP15_64(0, c9)
88 
89 static inline uint32_t get_id_dfr0(void) { return read_sysreg(ID_DFR0); }
90 static inline uint32_t get_pmcr(void) { return read_sysreg(PMCR); }
91 static inline void set_pmcr(uint32_t v) { write_sysreg(v, PMCR); }
92 static inline void set_pmcntenset(uint32_t v) { write_sysreg(v, PMCNTENSET); }
93 
94 static inline uint8_t get_pmu_version(void)
95 {
96 	return (get_id_dfr0() >> ID_DFR0_PERFMON_SHIFT) & ID_DFR0_PERFMON_MASK;
97 }
98 
99 static inline uint64_t get_pmccntr(void)
100 {
101 	return read_sysreg(PMCCNTR32);
102 }
103 
104 static inline void set_pmccntr(uint64_t value)
105 {
106 	write_sysreg(value & 0xffffffff, PMCCNTR32);
107 }
108 
109 /* PMCCFILTR is an obsolete name for PMXEVTYPER31 in ARMv7 */
110 static inline void set_pmccfiltr(uint32_t value)
111 {
112 	write_sysreg(PMU_CYCLE_IDX, PMSELR);
113 	write_sysreg(value, PMXEVTYPER);
114 	isb();
115 }
116 
117 /*
118  * Extra instructions inserted by the compiler would be difficult to compensate
119  * for, so hand assemble everything between, and including, the PMCR accesses
120  * to start and stop counting. isb instructions were inserted to make sure
121  * pmccntr read after this function returns the exact instructions executed in
122  * the controlled block. Total instrs = isb + mcr + 2*loop = 2 + 2*loop.
123  */
124 static inline void precise_instrs_loop(int loop, uint32_t pmcr)
125 {
126 	asm volatile(
127 	"	mcr	p15, 0, %[pmcr], c9, c12, 0\n"
128 	"	isb\n"
129 	"1:	subs	%[loop], %[loop], #1\n"
130 	"	bgt	1b\n"
131 	"	mcr	p15, 0, %[z], c9, c12, 0\n"
132 	"	isb\n"
133 	: [loop] "+r" (loop)
134 	: [pmcr] "r" (pmcr), [z] "r" (0)
135 	: "cc");
136 }
137 
138 /* event counter tests only implemented for aarch64 */
139 static void test_event_introspection(void) {}
140 static void test_event_counter_config(void) {}
141 static void test_basic_event_count(void) {}
142 static void test_mem_access(void) {}
143 
144 #elif defined(__aarch64__)
145 #define ID_AA64DFR0_PERFMON_SHIFT 8
146 #define ID_AA64DFR0_PERFMON_MASK  0xf
147 
148 #define ID_DFR0_PMU_NOTIMPL	0b0000
149 #define ID_DFR0_PMU_V3		0b0001
150 #define ID_DFR0_PMU_V3_8_1	0b0100
151 #define ID_DFR0_PMU_V3_8_4	0b0101
152 #define ID_DFR0_PMU_V3_8_5	0b0110
153 #define ID_DFR0_PMU_IMPDEF	0b1111
154 
155 static inline uint32_t get_id_aa64dfr0(void) { return read_sysreg(id_aa64dfr0_el1); }
156 static inline uint32_t get_pmcr(void) { return read_sysreg(pmcr_el0); }
157 static inline void set_pmcr(uint32_t v) { write_sysreg(v, pmcr_el0); }
158 static inline uint64_t get_pmccntr(void) { return read_sysreg(pmccntr_el0); }
159 static inline void set_pmccntr(uint64_t v) { write_sysreg(v, pmccntr_el0); }
160 static inline void set_pmcntenset(uint32_t v) { write_sysreg(v, pmcntenset_el0); }
161 static inline void set_pmccfiltr(uint32_t v) { write_sysreg(v, pmccfiltr_el0); }
162 
163 static inline uint8_t get_pmu_version(void)
164 {
165 	uint8_t ver = (get_id_aa64dfr0() >> ID_AA64DFR0_PERFMON_SHIFT) & ID_AA64DFR0_PERFMON_MASK;
166 	return ver;
167 }
168 
169 /*
170  * Extra instructions inserted by the compiler would be difficult to compensate
171  * for, so hand assemble everything between, and including, the PMCR accesses
172  * to start and stop counting. isb instructions are inserted to make sure
173  * pmccntr read after this function returns the exact instructions executed
174  * in the controlled block. Total instrs = isb + msr + 2*loop = 2 + 2*loop.
175  */
176 static inline void precise_instrs_loop(int loop, uint32_t pmcr)
177 {
178 	asm volatile(
179 	"	msr	pmcr_el0, %[pmcr]\n"
180 	"	isb\n"
181 	"1:	subs	%[loop], %[loop], #1\n"
182 	"	b.gt	1b\n"
183 	"	msr	pmcr_el0, xzr\n"
184 	"	isb\n"
185 	: [loop] "+r" (loop)
186 	: [pmcr] "r" (pmcr)
187 	: "cc");
188 }
189 
190 #define PMCEID1_EL0 sys_reg(3, 3, 9, 12, 7)
191 #define PMCNTENSET_EL0 sys_reg(3, 3, 9, 12, 1)
192 #define PMCNTENCLR_EL0 sys_reg(3, 3, 9, 12, 2)
193 
194 #define PMEVTYPER_EXCLUDE_EL1 BIT(31)
195 #define PMEVTYPER_EXCLUDE_EL0 BIT(30)
196 
197 static bool is_event_supported(uint32_t n, bool warn)
198 {
199 	uint64_t pmceid0 = read_sysreg(pmceid0_el0);
200 	uint64_t pmceid1 = read_sysreg_s(PMCEID1_EL0);
201 	bool supported;
202 	uint64_t reg;
203 
204 	/*
205 	 * The low 32-bits of PMCEID0/1 respectively describe
206 	 * event support for events 0-31/32-63. Their High
207 	 * 32-bits describe support for extended events
208 	 * starting at 0x4000, using the same split.
209 	 */
210 	assert((n >= COMMON_EVENTS_LOW  && n <= COMMON_EVENTS_HIGH) ||
211 	       (n >= EXT_COMMON_EVENTS_LOW && n <= EXT_COMMON_EVENTS_HIGH));
212 
213 	if (n <= COMMON_EVENTS_HIGH)
214 		reg = lower_32_bits(pmceid0) | ((u64)lower_32_bits(pmceid1) << 32);
215 	else
216 		reg = upper_32_bits(pmceid0) | ((u64)upper_32_bits(pmceid1) << 32);
217 
218 	supported =  reg & (1UL << (n & 0x3F));
219 
220 	if (!supported && warn)
221 		report_info("event 0x%x is not supported", n);
222 	return supported;
223 }
224 
225 static void test_event_introspection(void)
226 {
227 	bool required_events;
228 
229 	if (!pmu.nb_implemented_counters) {
230 		report_skip("No event counter, skip ...");
231 		return;
232 	}
233 
234 	/* PMUv3 requires an implementation includes some common events */
235 	required_events = is_event_supported(SW_INCR, true) &&
236 			  is_event_supported(CPU_CYCLES, true) &&
237 			  (is_event_supported(INST_RETIRED, true) ||
238 			   is_event_supported(INST_PREC, true));
239 
240 	if (pmu.version >= ID_DFR0_PMU_V3_8_1) {
241 		required_events = required_events &&
242 				  is_event_supported(STALL_FRONTEND, true) &&
243 				  is_event_supported(STALL_BACKEND, true);
244 	}
245 
246 	report(required_events, "Check required events are implemented");
247 }
248 
249 /*
250  * Extra instructions inserted by the compiler would be difficult to compensate
251  * for, so hand assemble everything between, and including, the PMCR accesses
252  * to start and stop counting. isb instructions are inserted to make sure
253  * pmccntr read after this function returns the exact instructions executed
254  * in the controlled block. Loads @loop times the data at @address into x9.
255  */
256 static void mem_access_loop(void *addr, int loop, uint32_t pmcr)
257 {
258 asm volatile(
259 	"       msr     pmcr_el0, %[pmcr]\n"
260 	"       isb\n"
261 	"       mov     x10, %[loop]\n"
262 	"1:     sub     x10, x10, #1\n"
263 	"       ldr	x9, [%[addr]]\n"
264 	"       cmp     x10, #0x0\n"
265 	"       b.gt    1b\n"
266 	"       msr     pmcr_el0, xzr\n"
267 	"       isb\n"
268 	:
269 	: [addr] "r" (addr), [pmcr] "r" (pmcr), [loop] "r" (loop)
270 	: "x9", "x10", "cc");
271 }
272 
273 static void pmu_reset(void)
274 {
275 	/* reset all counters, counting disabled at PMCR level*/
276 	set_pmcr(pmu.pmcr_ro | PMU_PMCR_LC | PMU_PMCR_C | PMU_PMCR_P);
277 	/* Disable all counters */
278 	write_sysreg_s(ALL_SET, PMCNTENCLR_EL0);
279 	/* clear overflow reg */
280 	write_sysreg(ALL_SET, pmovsclr_el0);
281 	/* disable overflow interrupts on all counters */
282 	write_sysreg(ALL_SET, pmintenclr_el1);
283 	isb();
284 }
285 
286 static void test_event_counter_config(void)
287 {
288 	int i;
289 
290 	if (!pmu.nb_implemented_counters) {
291 		report_skip("No event counter, skip ...");
292 		return;
293 	}
294 
295 	pmu_reset();
296 
297 	/*
298 	 * Test setting through PMESELR/PMXEVTYPER and PMEVTYPERn read,
299 	 * select counter 0
300 	 */
301 	write_sysreg(1, PMSELR_EL0);
302 	/* program this counter to count unsupported event */
303 	write_sysreg(0xEA, PMXEVTYPER_EL0);
304 	write_sysreg(0xdeadbeef, PMXEVCNTR_EL0);
305 	report((read_regn_el0(pmevtyper, 1) & 0xFFF) == 0xEA,
306 		"PMESELR/PMXEVTYPER/PMEVTYPERn");
307 	report((read_regn_el0(pmevcntr, 1) == 0xdeadbeef),
308 		"PMESELR/PMXEVCNTR/PMEVCNTRn");
309 
310 	/* try to configure an unsupported event within the range [0x0, 0x3F] */
311 	for (i = 0; i <= 0x3F; i++) {
312 		if (!is_event_supported(i, false))
313 			break;
314 	}
315 	if (i > 0x3F) {
316 		report_skip("pmevtyper: all events within [0x0, 0x3F] are supported");
317 		return;
318 	}
319 
320 	/* select counter 0 */
321 	write_sysreg(0, PMSELR_EL0);
322 	/* program this counter to count unsupported event */
323 	write_sysreg(i, PMXEVCNTR_EL0);
324 	/* read the counter value */
325 	read_sysreg(PMXEVCNTR_EL0);
326 	report(read_sysreg(PMXEVCNTR_EL0) == i,
327 		"read of a counter programmed with unsupported event");
328 }
329 
330 static bool satisfy_prerequisites(uint32_t *events, unsigned int nb_events)
331 {
332 	int i;
333 
334 	if (pmu.nb_implemented_counters < nb_events) {
335 		report_skip("Skip test as number of counters is too small (%d)",
336 			    pmu.nb_implemented_counters);
337 		return false;
338 	}
339 
340 	for (i = 0; i < nb_events; i++) {
341 		if (!is_event_supported(events[i], false)) {
342 			report_skip("Skip test as event 0x%x is not supported",
343 				    events[i]);
344 			return false;
345 		}
346 	}
347 	return true;
348 }
349 
350 static void test_basic_event_count(void)
351 {
352 	uint32_t implemented_counter_mask, non_implemented_counter_mask;
353 	uint32_t counter_mask;
354 	uint32_t events[] = {CPU_CYCLES, INST_RETIRED};
355 
356 	if (!satisfy_prerequisites(events, ARRAY_SIZE(events)))
357 		return;
358 
359 	implemented_counter_mask = BIT(pmu.nb_implemented_counters) - 1;
360 	non_implemented_counter_mask = ~(BIT(31) | implemented_counter_mask);
361 	counter_mask = implemented_counter_mask | non_implemented_counter_mask;
362 
363 	write_regn_el0(pmevtyper, 0, CPU_CYCLES | PMEVTYPER_EXCLUDE_EL0);
364 	write_regn_el0(pmevtyper, 1, INST_RETIRED | PMEVTYPER_EXCLUDE_EL0);
365 
366 	/* disable all counters */
367 	write_sysreg_s(ALL_SET, PMCNTENCLR_EL0);
368 	report(!read_sysreg_s(PMCNTENCLR_EL0) && !read_sysreg_s(PMCNTENSET_EL0),
369 		"pmcntenclr: disable all counters");
370 
371 	/*
372 	 * clear cycle and all event counters and allow counter enablement
373 	 * through PMCNTENSET. LC is RES1.
374 	 */
375 	set_pmcr(pmu.pmcr_ro | PMU_PMCR_LC | PMU_PMCR_C | PMU_PMCR_P);
376 	isb();
377 	report(get_pmcr() == (pmu.pmcr_ro | PMU_PMCR_LC), "pmcr: reset counters");
378 
379 	/* Preset counter #0 to pre overflow value to trigger an overflow */
380 	write_regn_el0(pmevcntr, 0, PRE_OVERFLOW);
381 	report(read_regn_el0(pmevcntr, 0) == PRE_OVERFLOW,
382 		"counter #0 preset to pre-overflow value");
383 	report(!read_regn_el0(pmevcntr, 1), "counter #1 is 0");
384 
385 	/*
386 	 * Enable all implemented counters and also attempt to enable
387 	 * not supported counters. Counting still is disabled by !PMCR.E
388 	 */
389 	write_sysreg_s(counter_mask, PMCNTENSET_EL0);
390 
391 	/* check only those implemented are enabled */
392 	report((read_sysreg_s(PMCNTENSET_EL0) == read_sysreg_s(PMCNTENCLR_EL0)) &&
393 		(read_sysreg_s(PMCNTENSET_EL0) == implemented_counter_mask),
394 		"pmcntenset: enabled implemented_counters");
395 
396 	/* Disable all counters but counters #0 and #1 */
397 	write_sysreg_s(~0x3, PMCNTENCLR_EL0);
398 	report((read_sysreg_s(PMCNTENSET_EL0) == read_sysreg_s(PMCNTENCLR_EL0)) &&
399 		(read_sysreg_s(PMCNTENSET_EL0) == 0x3),
400 		"pmcntenset: just enabled #0 and #1");
401 
402 	/* clear overflow register */
403 	write_sysreg(ALL_SET, pmovsclr_el0);
404 	report(!read_sysreg(pmovsclr_el0), "check overflow reg is 0");
405 
406 	/* disable overflow interrupts on all counters*/
407 	write_sysreg(ALL_SET, pmintenclr_el1);
408 	report(!read_sysreg(pmintenclr_el1),
409 		"pmintenclr_el1=0, all interrupts disabled");
410 
411 	/* enable overflow interrupts on all event counters */
412 	write_sysreg(implemented_counter_mask | non_implemented_counter_mask,
413 		     pmintenset_el1);
414 	report(read_sysreg(pmintenset_el1) == implemented_counter_mask,
415 		"overflow interrupts enabled on all implemented counters");
416 
417 	/* Set PMCR.E, execute asm code and unset PMCR.E */
418 	precise_instrs_loop(20, pmu.pmcr_ro | PMU_PMCR_E);
419 
420 	report_info("counter #0 is 0x%lx (CPU_CYCLES)",
421 		    read_regn_el0(pmevcntr, 0));
422 	report_info("counter #1 is 0x%lx (INST_RETIRED)",
423 		    read_regn_el0(pmevcntr, 1));
424 
425 	report_info("overflow reg = 0x%lx", read_sysreg(pmovsclr_el0));
426 	report(read_sysreg(pmovsclr_el0) & 0x1,
427 		"check overflow happened on #0 only");
428 }
429 
430 static void test_mem_access(void)
431 {
432 	void *addr = malloc(PAGE_SIZE);
433 	uint32_t events[] = {MEM_ACCESS, MEM_ACCESS};
434 
435 	if (!satisfy_prerequisites(events, ARRAY_SIZE(events)))
436 		return;
437 
438 	pmu_reset();
439 
440 	write_regn_el0(pmevtyper, 0, MEM_ACCESS | PMEVTYPER_EXCLUDE_EL0);
441 	write_regn_el0(pmevtyper, 1, MEM_ACCESS | PMEVTYPER_EXCLUDE_EL0);
442 	write_sysreg_s(0x3, PMCNTENSET_EL0);
443 	isb();
444 	mem_access_loop(addr, 20, pmu.pmcr_ro | PMU_PMCR_E);
445 	report_info("counter #0 is %ld (MEM_ACCESS)", read_regn_el0(pmevcntr, 0));
446 	report_info("counter #1 is %ld (MEM_ACCESS)", read_regn_el0(pmevcntr, 1));
447 	/* We may measure more than 20 mem access depending on the core */
448 	report((read_regn_el0(pmevcntr, 0) == read_regn_el0(pmevcntr, 1)) &&
449 	       (read_regn_el0(pmevcntr, 0) >= 20) && !read_sysreg(pmovsclr_el0),
450 	       "Ran 20 mem accesses");
451 
452 	pmu_reset();
453 
454 	write_regn_el0(pmevcntr, 0, PRE_OVERFLOW);
455 	write_regn_el0(pmevcntr, 1, PRE_OVERFLOW);
456 	write_sysreg_s(0x3, PMCNTENSET_EL0);
457 	isb();
458 	mem_access_loop(addr, 20, pmu.pmcr_ro | PMU_PMCR_E);
459 	report(read_sysreg(pmovsclr_el0) == 0x3,
460 	       "Ran 20 mem accesses with expected overflows on both counters");
461 	report_info("cnt#0 = %ld cnt#1=%ld overflow=0x%lx",
462 			read_regn_el0(pmevcntr, 0), read_regn_el0(pmevcntr, 1),
463 			read_sysreg(pmovsclr_el0));
464 }
465 
466 #endif
467 
468 /*
469  * Ensure that the cycle counter progresses between back-to-back reads.
470  */
471 static bool check_cycles_increase(void)
472 {
473 	bool success = true;
474 
475 	/* init before event access, this test only cares about cycle count */
476 	set_pmcntenset(1 << PMU_CYCLE_IDX);
477 	set_pmccfiltr(0); /* count cycles in EL0, EL1, but not EL2 */
478 
479 	set_pmcr(get_pmcr() | PMU_PMCR_LC | PMU_PMCR_C | PMU_PMCR_E);
480 
481 	for (int i = 0; i < NR_SAMPLES; i++) {
482 		uint64_t a, b;
483 
484 		a = get_pmccntr();
485 		b = get_pmccntr();
486 
487 		if (a >= b) {
488 			printf("Read %"PRId64" then %"PRId64".\n", a, b);
489 			success = false;
490 			break;
491 		}
492 	}
493 
494 	set_pmcr(get_pmcr() & ~PMU_PMCR_E);
495 
496 	return success;
497 }
498 
499 /*
500  * Execute a known number of guest instructions. Only even instruction counts
501  * greater than or equal to 4 are supported by the in-line assembly code. The
502  * control register (PMCR_EL0) is initialized with the provided value (allowing
503  * for example for the cycle counter or event counters to be reset). At the end
504  * of the exact instruction loop, zero is written to PMCR_EL0 to disable
505  * counting, allowing the cycle counter or event counters to be read at the
506  * leisure of the calling code.
507  */
508 static void measure_instrs(int num, uint32_t pmcr)
509 {
510 	int loop = (num - 2) / 2;
511 
512 	assert(num >= 4 && ((num - 2) % 2 == 0));
513 	precise_instrs_loop(loop, pmcr);
514 }
515 
516 /*
517  * Measure cycle counts for various known instruction counts. Ensure that the
518  * cycle counter progresses (similar to check_cycles_increase() but with more
519  * instructions and using reset and stop controls). If supplied a positive,
520  * nonzero CPI parameter, it also strictly checks that every measurement matches
521  * it. Strict CPI checking is used to test -icount mode.
522  */
523 static bool check_cpi(int cpi)
524 {
525 	uint32_t pmcr = get_pmcr() | PMU_PMCR_LC | PMU_PMCR_C | PMU_PMCR_E;
526 
527 	/* init before event access, this test only cares about cycle count */
528 	set_pmcntenset(1 << PMU_CYCLE_IDX);
529 	set_pmccfiltr(0); /* count cycles in EL0, EL1, but not EL2 */
530 
531 	if (cpi > 0)
532 		printf("Checking for CPI=%d.\n", cpi);
533 	printf("instrs : cycles0 cycles1 ...\n");
534 
535 	for (unsigned int i = 4; i < 300; i += 32) {
536 		uint64_t avg, sum = 0;
537 
538 		printf("%4d:", i);
539 		for (int j = 0; j < NR_SAMPLES; j++) {
540 			uint64_t cycles;
541 
542 			set_pmccntr(0);
543 			measure_instrs(i, pmcr);
544 			cycles = get_pmccntr();
545 			printf(" %4"PRId64"", cycles);
546 
547 			if (!cycles) {
548 				printf("\ncycles not incrementing!\n");
549 				return false;
550 			} else if (cpi > 0 && cycles != i * cpi) {
551 				printf("\nunexpected cycle count received!\n");
552 				return false;
553 			} else if ((cycles >> 32) != 0) {
554 				/* The cycles taken by the loop above should
555 				 * fit in 32 bits easily. We check the upper
556 				 * 32 bits of the cycle counter to make sure
557 				 * there is no supprise. */
558 				printf("\ncycle count bigger than 32bit!\n");
559 				return false;
560 			}
561 
562 			sum += cycles;
563 		}
564 		avg = sum / NR_SAMPLES;
565 		printf(" avg=%-4"PRId64" %s=%-3"PRId64"\n", avg,
566 		       (avg >= i) ? "cpi" : "ipc",
567 		       (avg >= i) ? avg / i : i / avg);
568 	}
569 
570 	return true;
571 }
572 
573 static void pmccntr64_test(void)
574 {
575 #ifdef __arm__
576 	if (pmu.version == ID_DFR0_PMU_V3) {
577 		if (ERRATA(9e3f7a296940)) {
578 			write_sysreg(0xdead, PMCCNTR64);
579 			report(read_sysreg(PMCCNTR64) == 0xdead, "pmccntr64");
580 		} else
581 			report_skip("Skipping unsafe pmccntr64 test. Set ERRATA_9e3f7a296940=y to enable.");
582 	}
583 #endif
584 }
585 
586 /* Return FALSE if no PMU found, otherwise return TRUE */
587 static bool pmu_probe(void)
588 {
589 	uint32_t pmcr = get_pmcr();
590 
591 	pmu.version = get_pmu_version();
592 	if (pmu.version == ID_DFR0_PMU_NOTIMPL || pmu.version == ID_DFR0_PMU_IMPDEF)
593 		return false;
594 
595 	report_info("PMU version: 0x%x", pmu.version);
596 
597 	pmcr = get_pmcr();
598 	report_info("PMU implementer/ID code: %#x(\"%c\")/%#x",
599 		    (pmcr >> PMU_PMCR_IMP_SHIFT) & PMU_PMCR_IMP_MASK,
600 		    ((pmcr >> PMU_PMCR_IMP_SHIFT) & PMU_PMCR_IMP_MASK) ? : ' ',
601 		    (pmcr >> PMU_PMCR_ID_SHIFT) & PMU_PMCR_ID_MASK);
602 
603 	/* store read-only and RES0 fields of the PMCR bottom-half*/
604 	pmu.pmcr_ro = pmcr & 0xFFFFFF00;
605 	pmu.nb_implemented_counters =
606 		(pmcr >> PMU_PMCR_N_SHIFT) & PMU_PMCR_N_MASK;
607 	report_info("Implements %d event counters",
608 		    pmu.nb_implemented_counters);
609 
610 	return true;
611 }
612 
613 int main(int argc, char *argv[])
614 {
615 	int cpi = 0;
616 
617 	if (!pmu_probe()) {
618 		printf("No PMU found, test skipped...\n");
619 		return report_summary();
620 	}
621 
622 	if (argc < 2)
623 		report_abort("no test specified");
624 
625 	report_prefix_push("pmu");
626 
627 	if (strcmp(argv[1], "cycle-counter") == 0) {
628 		report_prefix_push(argv[1]);
629 		if (argc > 2)
630 			cpi = atol(argv[2]);
631 		report(check_cycles_increase(),
632 		       "Monotonically increasing cycle count");
633 		report(check_cpi(cpi), "Cycle/instruction ratio");
634 		pmccntr64_test();
635 		report_prefix_pop();
636 	} else if (strcmp(argv[1], "pmu-event-introspection") == 0) {
637 		report_prefix_push(argv[1]);
638 		test_event_introspection();
639 		report_prefix_pop();
640 	} else if (strcmp(argv[1], "pmu-event-counter-config") == 0) {
641 		report_prefix_push(argv[1]);
642 		test_event_counter_config();
643 		report_prefix_pop();
644 	} else if (strcmp(argv[1], "pmu-basic-event-count") == 0) {
645 		report_prefix_push(argv[1]);
646 		test_basic_event_count();
647 		report_prefix_pop();
648 	} else if (strcmp(argv[1], "pmu-mem-access") == 0) {
649 		report_prefix_push(argv[1]);
650 		test_mem_access();
651 		report_prefix_pop();
652 	} else {
653 		report_abort("Unknown sub-test '%s'", argv[1]);
654 	}
655 
656 	return report_summary();
657 }
658