1 /*
2  * Copyright 2014, Michael Ellerman, IBM Corp.
3  * Licensed under GPLv2.
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 	/* Use PMC2 so we set PMCjCE, which enables PMC5/6 */
53 	event_init(&event, 0x2001e);
54 	event_leader_ebb_init(&event);
55 
56 	event.attr.exclude_kernel = 1;
57 	event.attr.exclude_hv = 1;
58 	event.attr.exclude_idle = 1;
59 
60 	FAIL_IF(event_open(&event));
61 
62 	setup_ebb_handler(ebb_callee);
63 	ebb_global_enable();
64 
65 	FAIL_IF(ebb_event_enable(&event));
66 
67 	mtspr(SPRN_PMC1, pmc_sample_period(sample_period));
68 	mtspr(SPRN_PMC5, 0);
69 	mtspr(SPRN_PMC6, 0);
70 
71 	while (ebb_state.stats.ebb_count < 10)
72 		FAIL_IF(core_busy_loop());
73 
74 	ebb_global_disable();
75 	ebb_freeze_pmcs();
76 
77 	count_pmc(2, sample_period);
78 
79 	dump_ebb_state();
80 
81 	printf("PMC5/6 overflow %d\n", pmc56_overflowed);
82 
83 	event_close(&event);
84 
85 	FAIL_IF(ebb_state.stats.ebb_count == 0 || pmc56_overflowed != 0);
86 
87 	return 0;
88 }
89 
90 int main(void)
91 {
92 	return test_harness(pmc56_overflow, "pmc56_overflow");
93 }
94