1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright 2014, Michael Ellerman, IBM Corp.
4  */
5 
6 #include <stdio.h>
7 #include <stdlib.h>
8 
9 #include "ebb.h"
10 
11 
12 /*
13  * Test that PMC5 & 6 are frozen (ie. don't overflow) when they are not being
14  * used. Tests the MMCR0_FC56 logic in the kernel.
15  */
16 
17 static int pmc56_overflowed;
18 
19 static void ebb_callee(void)
20 {
21 	uint64_t val;
22 
23 	val = mfspr(SPRN_BESCR);
24 	if (!(val & BESCR_PMEO)) {
25 		ebb_state.stats.spurious++;
26 		goto out;
27 	}
28 
29 	ebb_state.stats.ebb_count++;
30 	count_pmc(2, sample_period);
31 
32 	val = mfspr(SPRN_PMC5);
33 	if (val >= COUNTER_OVERFLOW)
34 		pmc56_overflowed++;
35 
36 	count_pmc(5, COUNTER_OVERFLOW);
37 
38 	val = mfspr(SPRN_PMC6);
39 	if (val >= COUNTER_OVERFLOW)
40 		pmc56_overflowed++;
41 
42 	count_pmc(6, COUNTER_OVERFLOW);
43 
44 out:
45 	reset_ebb();
46 }
47 
48 int pmc56_overflow(void)
49 {
50 	struct event event;
51 
52 	SKIP_IF(!ebb_is_supported());
53 
54 	/* Use PMC2 so we set PMCjCE, which enables PMC5/6 */
55 	event_init(&event, 0x2001e);
56 	event_leader_ebb_init(&event);
57 
58 	event.attr.exclude_kernel = 1;
59 	event.attr.exclude_hv = 1;
60 	event.attr.exclude_idle = 1;
61 
62 	FAIL_IF(event_open(&event));
63 
64 	setup_ebb_handler(ebb_callee);
65 	ebb_global_enable();
66 
67 	FAIL_IF(ebb_event_enable(&event));
68 
69 	mtspr(SPRN_PMC2, pmc_sample_period(sample_period));
70 	mtspr(SPRN_PMC5, 0);
71 	mtspr(SPRN_PMC6, 0);
72 
73 	while (ebb_state.stats.ebb_count < 10)
74 		FAIL_IF(core_busy_loop());
75 
76 	ebb_global_disable();
77 	ebb_freeze_pmcs();
78 
79 	count_pmc(2, sample_period);
80 
81 	dump_ebb_state();
82 
83 	printf("PMC5/6 overflow %d\n", pmc56_overflowed);
84 
85 	event_close(&event);
86 
87 	FAIL_IF(ebb_state.stats.ebb_count == 0 || pmc56_overflowed != 0);
88 
89 	return 0;
90 }
91 
92 int main(void)
93 {
94 	return test_harness(pmc56_overflow, "pmc56_overflow");
95 }
96