xref: /OK3568_Linux_fs/kernel/tools/testing/selftests/powerpc/pmu/ebb/ebb.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Copyright 2014, Michael Ellerman, IBM Corp.
4*4882a593Smuzhiyun  */
5*4882a593Smuzhiyun 
6*4882a593Smuzhiyun #define _GNU_SOURCE	/* For CPU_ZERO etc. */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include <sched.h>
9*4882a593Smuzhiyun #include <sys/wait.h>
10*4882a593Smuzhiyun #include <setjmp.h>
11*4882a593Smuzhiyun #include <signal.h>
12*4882a593Smuzhiyun #include <stdio.h>
13*4882a593Smuzhiyun #include <stdlib.h>
14*4882a593Smuzhiyun #include <string.h>
15*4882a593Smuzhiyun #include <sys/ioctl.h>
16*4882a593Smuzhiyun 
17*4882a593Smuzhiyun #include "trace.h"
18*4882a593Smuzhiyun #include "ebb.h"
19*4882a593Smuzhiyun 
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun void (*ebb_user_func)(void);
22*4882a593Smuzhiyun 
ebb_hook(void)23*4882a593Smuzhiyun void ebb_hook(void)
24*4882a593Smuzhiyun {
25*4882a593Smuzhiyun 	if (ebb_user_func)
26*4882a593Smuzhiyun 		ebb_user_func();
27*4882a593Smuzhiyun }
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun struct ebb_state ebb_state;
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun u64 sample_period = 0x40000000ull;
32*4882a593Smuzhiyun 
reset_ebb_with_clear_mask(unsigned long mmcr0_clear_mask)33*4882a593Smuzhiyun void reset_ebb_with_clear_mask(unsigned long mmcr0_clear_mask)
34*4882a593Smuzhiyun {
35*4882a593Smuzhiyun 	u64 val;
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun 	/* 2) clear MMCR0[PMAO] - docs say BESCR[PMEO] should do this */
38*4882a593Smuzhiyun 	/* 3) set MMCR0[PMAE]	- docs say BESCR[PME] should do this */
39*4882a593Smuzhiyun 	val = mfspr(SPRN_MMCR0);
40*4882a593Smuzhiyun 	mtspr(SPRN_MMCR0, (val & ~mmcr0_clear_mask) | MMCR0_PMAE);
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun 	/* 4) clear BESCR[PMEO] */
43*4882a593Smuzhiyun 	mtspr(SPRN_BESCRR, BESCR_PMEO);
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun 	/* 5) set BESCR[PME] */
46*4882a593Smuzhiyun 	mtspr(SPRN_BESCRS, BESCR_PME);
47*4882a593Smuzhiyun 
48*4882a593Smuzhiyun 	/* 6) rfebb 1 - done in our caller */
49*4882a593Smuzhiyun }
50*4882a593Smuzhiyun 
reset_ebb(void)51*4882a593Smuzhiyun void reset_ebb(void)
52*4882a593Smuzhiyun {
53*4882a593Smuzhiyun 	reset_ebb_with_clear_mask(MMCR0_PMAO | MMCR0_FC);
54*4882a593Smuzhiyun }
55*4882a593Smuzhiyun 
56*4882a593Smuzhiyun /* Called outside of the EBB handler to check MMCR0 is sane */
ebb_check_mmcr0(void)57*4882a593Smuzhiyun int ebb_check_mmcr0(void)
58*4882a593Smuzhiyun {
59*4882a593Smuzhiyun 	u64 val;
60*4882a593Smuzhiyun 
61*4882a593Smuzhiyun 	val = mfspr(SPRN_MMCR0);
62*4882a593Smuzhiyun 	if ((val & (MMCR0_FC | MMCR0_PMAO)) == MMCR0_FC) {
63*4882a593Smuzhiyun 		/* It's OK if we see FC & PMAO, but not FC by itself */
64*4882a593Smuzhiyun 		printf("Outside of loop, only FC set 0x%llx\n", val);
65*4882a593Smuzhiyun 		return 1;
66*4882a593Smuzhiyun 	}
67*4882a593Smuzhiyun 
68*4882a593Smuzhiyun 	return 0;
69*4882a593Smuzhiyun }
70*4882a593Smuzhiyun 
ebb_check_count(int pmc,u64 sample_period,int fudge)71*4882a593Smuzhiyun bool ebb_check_count(int pmc, u64 sample_period, int fudge)
72*4882a593Smuzhiyun {
73*4882a593Smuzhiyun 	u64 count, upper, lower;
74*4882a593Smuzhiyun 
75*4882a593Smuzhiyun 	count = ebb_state.stats.pmc_count[PMC_INDEX(pmc)];
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun 	lower = ebb_state.stats.ebb_count * (sample_period - fudge);
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun 	if (count < lower) {
80*4882a593Smuzhiyun 		printf("PMC%d count (0x%llx) below lower limit 0x%llx (-0x%llx)\n",
81*4882a593Smuzhiyun 			pmc, count, lower, lower - count);
82*4882a593Smuzhiyun 		return false;
83*4882a593Smuzhiyun 	}
84*4882a593Smuzhiyun 
85*4882a593Smuzhiyun 	upper = ebb_state.stats.ebb_count * (sample_period + fudge);
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun 	if (count > upper) {
88*4882a593Smuzhiyun 		printf("PMC%d count (0x%llx) above upper limit 0x%llx (+0x%llx)\n",
89*4882a593Smuzhiyun 			pmc, count, upper, count - upper);
90*4882a593Smuzhiyun 		return false;
91*4882a593Smuzhiyun 	}
92*4882a593Smuzhiyun 
93*4882a593Smuzhiyun 	printf("PMC%d count (0x%llx) is between 0x%llx and 0x%llx delta +0x%llx/-0x%llx\n",
94*4882a593Smuzhiyun 		pmc, count, lower, upper, count - lower, upper - count);
95*4882a593Smuzhiyun 
96*4882a593Smuzhiyun 	return true;
97*4882a593Smuzhiyun }
98*4882a593Smuzhiyun 
standard_ebb_callee(void)99*4882a593Smuzhiyun void standard_ebb_callee(void)
100*4882a593Smuzhiyun {
101*4882a593Smuzhiyun 	int found, i;
102*4882a593Smuzhiyun 	u64 val;
103*4882a593Smuzhiyun 
104*4882a593Smuzhiyun 	val = mfspr(SPRN_BESCR);
105*4882a593Smuzhiyun 	if (!(val & BESCR_PMEO)) {
106*4882a593Smuzhiyun 		ebb_state.stats.spurious++;
107*4882a593Smuzhiyun 		goto out;
108*4882a593Smuzhiyun 	}
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun 	ebb_state.stats.ebb_count++;
111*4882a593Smuzhiyun 	trace_log_counter(ebb_state.trace, ebb_state.stats.ebb_count);
112*4882a593Smuzhiyun 
113*4882a593Smuzhiyun 	val = mfspr(SPRN_MMCR0);
114*4882a593Smuzhiyun 	trace_log_reg(ebb_state.trace, SPRN_MMCR0, val);
115*4882a593Smuzhiyun 
116*4882a593Smuzhiyun 	found = 0;
117*4882a593Smuzhiyun 	for (i = 1; i <= 6; i++) {
118*4882a593Smuzhiyun 		if (ebb_state.pmc_enable[PMC_INDEX(i)])
119*4882a593Smuzhiyun 			found += count_pmc(i, sample_period);
120*4882a593Smuzhiyun 	}
121*4882a593Smuzhiyun 
122*4882a593Smuzhiyun 	if (!found)
123*4882a593Smuzhiyun 		ebb_state.stats.no_overflow++;
124*4882a593Smuzhiyun 
125*4882a593Smuzhiyun out:
126*4882a593Smuzhiyun 	reset_ebb();
127*4882a593Smuzhiyun }
128*4882a593Smuzhiyun 
129*4882a593Smuzhiyun extern void ebb_handler(void);
130*4882a593Smuzhiyun 
setup_ebb_handler(void (* callee)(void))131*4882a593Smuzhiyun void setup_ebb_handler(void (*callee)(void))
132*4882a593Smuzhiyun {
133*4882a593Smuzhiyun 	u64 entry;
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun #if defined(_CALL_ELF) && _CALL_ELF == 2
136*4882a593Smuzhiyun 	entry = (u64)ebb_handler;
137*4882a593Smuzhiyun #else
138*4882a593Smuzhiyun 	struct opd
139*4882a593Smuzhiyun 	{
140*4882a593Smuzhiyun 	    u64 entry;
141*4882a593Smuzhiyun 	    u64 toc;
142*4882a593Smuzhiyun 	} *opd;
143*4882a593Smuzhiyun 
144*4882a593Smuzhiyun 	opd = (struct opd *)ebb_handler;
145*4882a593Smuzhiyun 	entry = opd->entry;
146*4882a593Smuzhiyun #endif
147*4882a593Smuzhiyun 	printf("EBB Handler is at %#llx\n", entry);
148*4882a593Smuzhiyun 
149*4882a593Smuzhiyun 	ebb_user_func = callee;
150*4882a593Smuzhiyun 
151*4882a593Smuzhiyun 	/* Ensure ebb_user_func is set before we set the handler */
152*4882a593Smuzhiyun 	mb();
153*4882a593Smuzhiyun 	mtspr(SPRN_EBBHR, entry);
154*4882a593Smuzhiyun 
155*4882a593Smuzhiyun 	/* Make sure the handler is set before we return */
156*4882a593Smuzhiyun 	mb();
157*4882a593Smuzhiyun }
158*4882a593Smuzhiyun 
clear_ebb_stats(void)159*4882a593Smuzhiyun void clear_ebb_stats(void)
160*4882a593Smuzhiyun {
161*4882a593Smuzhiyun 	memset(&ebb_state.stats, 0, sizeof(ebb_state.stats));
162*4882a593Smuzhiyun }
163*4882a593Smuzhiyun 
dump_summary_ebb_state(void)164*4882a593Smuzhiyun void dump_summary_ebb_state(void)
165*4882a593Smuzhiyun {
166*4882a593Smuzhiyun 	printf("ebb_state:\n"			\
167*4882a593Smuzhiyun 	       "  ebb_count    = %d\n"		\
168*4882a593Smuzhiyun 	       "  spurious     = %d\n"		\
169*4882a593Smuzhiyun 	       "  negative     = %d\n"		\
170*4882a593Smuzhiyun 	       "  no_overflow  = %d\n"		\
171*4882a593Smuzhiyun 	       "  pmc[1] count = 0x%llx\n"	\
172*4882a593Smuzhiyun 	       "  pmc[2] count = 0x%llx\n"	\
173*4882a593Smuzhiyun 	       "  pmc[3] count = 0x%llx\n"	\
174*4882a593Smuzhiyun 	       "  pmc[4] count = 0x%llx\n"	\
175*4882a593Smuzhiyun 	       "  pmc[5] count = 0x%llx\n"	\
176*4882a593Smuzhiyun 	       "  pmc[6] count = 0x%llx\n",
177*4882a593Smuzhiyun 		ebb_state.stats.ebb_count, ebb_state.stats.spurious,
178*4882a593Smuzhiyun 		ebb_state.stats.negative, ebb_state.stats.no_overflow,
179*4882a593Smuzhiyun 		ebb_state.stats.pmc_count[0], ebb_state.stats.pmc_count[1],
180*4882a593Smuzhiyun 		ebb_state.stats.pmc_count[2], ebb_state.stats.pmc_count[3],
181*4882a593Smuzhiyun 		ebb_state.stats.pmc_count[4], ebb_state.stats.pmc_count[5]);
182*4882a593Smuzhiyun }
183*4882a593Smuzhiyun 
decode_mmcr0(u32 value)184*4882a593Smuzhiyun static char *decode_mmcr0(u32 value)
185*4882a593Smuzhiyun {
186*4882a593Smuzhiyun 	static char buf[16];
187*4882a593Smuzhiyun 
188*4882a593Smuzhiyun 	buf[0] = '\0';
189*4882a593Smuzhiyun 
190*4882a593Smuzhiyun 	if (value & (1 << 31))
191*4882a593Smuzhiyun 		strcat(buf, "FC ");
192*4882a593Smuzhiyun 	if (value & (1 << 26))
193*4882a593Smuzhiyun 		strcat(buf, "PMAE ");
194*4882a593Smuzhiyun 	if (value & (1 << 7))
195*4882a593Smuzhiyun 		strcat(buf, "PMAO ");
196*4882a593Smuzhiyun 
197*4882a593Smuzhiyun 	return buf;
198*4882a593Smuzhiyun }
199*4882a593Smuzhiyun 
decode_bescr(u64 value)200*4882a593Smuzhiyun static char *decode_bescr(u64 value)
201*4882a593Smuzhiyun {
202*4882a593Smuzhiyun 	static char buf[16];
203*4882a593Smuzhiyun 
204*4882a593Smuzhiyun 	buf[0] = '\0';
205*4882a593Smuzhiyun 
206*4882a593Smuzhiyun 	if (value & (1ull << 63))
207*4882a593Smuzhiyun 		strcat(buf, "GE ");
208*4882a593Smuzhiyun 	if (value & (1ull << 32))
209*4882a593Smuzhiyun 		strcat(buf, "PMAE ");
210*4882a593Smuzhiyun 	if (value & 1)
211*4882a593Smuzhiyun 		strcat(buf, "PMAO ");
212*4882a593Smuzhiyun 
213*4882a593Smuzhiyun 	return buf;
214*4882a593Smuzhiyun }
215*4882a593Smuzhiyun 
dump_ebb_hw_state(void)216*4882a593Smuzhiyun void dump_ebb_hw_state(void)
217*4882a593Smuzhiyun {
218*4882a593Smuzhiyun 	u64 bescr;
219*4882a593Smuzhiyun 	u32 mmcr0;
220*4882a593Smuzhiyun 
221*4882a593Smuzhiyun 	mmcr0 = mfspr(SPRN_MMCR0);
222*4882a593Smuzhiyun 	bescr = mfspr(SPRN_BESCR);
223*4882a593Smuzhiyun 
224*4882a593Smuzhiyun 	printf("HW state:\n"		\
225*4882a593Smuzhiyun 	       "MMCR0 0x%016x %s\n"	\
226*4882a593Smuzhiyun 	       "MMCR2 0x%016lx\n"	\
227*4882a593Smuzhiyun 	       "EBBHR 0x%016lx\n"	\
228*4882a593Smuzhiyun 	       "BESCR 0x%016llx %s\n"	\
229*4882a593Smuzhiyun 	       "PMC1  0x%016lx\n"	\
230*4882a593Smuzhiyun 	       "PMC2  0x%016lx\n"	\
231*4882a593Smuzhiyun 	       "PMC3  0x%016lx\n"	\
232*4882a593Smuzhiyun 	       "PMC4  0x%016lx\n"	\
233*4882a593Smuzhiyun 	       "PMC5  0x%016lx\n"	\
234*4882a593Smuzhiyun 	       "PMC6  0x%016lx\n"	\
235*4882a593Smuzhiyun 	       "SIAR  0x%016lx\n",
236*4882a593Smuzhiyun 	       mmcr0, decode_mmcr0(mmcr0), mfspr(SPRN_MMCR2),
237*4882a593Smuzhiyun 	       mfspr(SPRN_EBBHR), bescr, decode_bescr(bescr),
238*4882a593Smuzhiyun 	       mfspr(SPRN_PMC1), mfspr(SPRN_PMC2), mfspr(SPRN_PMC3),
239*4882a593Smuzhiyun 	       mfspr(SPRN_PMC4), mfspr(SPRN_PMC5), mfspr(SPRN_PMC6),
240*4882a593Smuzhiyun 	       mfspr(SPRN_SIAR));
241*4882a593Smuzhiyun }
242*4882a593Smuzhiyun 
dump_ebb_state(void)243*4882a593Smuzhiyun void dump_ebb_state(void)
244*4882a593Smuzhiyun {
245*4882a593Smuzhiyun 	dump_summary_ebb_state();
246*4882a593Smuzhiyun 
247*4882a593Smuzhiyun 	dump_ebb_hw_state();
248*4882a593Smuzhiyun 
249*4882a593Smuzhiyun 	trace_buffer_print(ebb_state.trace);
250*4882a593Smuzhiyun }
251*4882a593Smuzhiyun 
count_pmc(int pmc,uint32_t sample_period)252*4882a593Smuzhiyun int count_pmc(int pmc, uint32_t sample_period)
253*4882a593Smuzhiyun {
254*4882a593Smuzhiyun 	uint32_t start_value;
255*4882a593Smuzhiyun 	u64 val;
256*4882a593Smuzhiyun 
257*4882a593Smuzhiyun 	/* 0) Read PMC */
258*4882a593Smuzhiyun 	start_value = pmc_sample_period(sample_period);
259*4882a593Smuzhiyun 
260*4882a593Smuzhiyun 	val = read_pmc(pmc);
261*4882a593Smuzhiyun 	if (val < start_value)
262*4882a593Smuzhiyun 		ebb_state.stats.negative++;
263*4882a593Smuzhiyun 	else
264*4882a593Smuzhiyun 		ebb_state.stats.pmc_count[PMC_INDEX(pmc)] += val - start_value;
265*4882a593Smuzhiyun 
266*4882a593Smuzhiyun 	trace_log_reg(ebb_state.trace, SPRN_PMC1 + pmc - 1, val);
267*4882a593Smuzhiyun 
268*4882a593Smuzhiyun 	/* 1) Reset PMC */
269*4882a593Smuzhiyun 	write_pmc(pmc, start_value);
270*4882a593Smuzhiyun 
271*4882a593Smuzhiyun 	/* Report if we overflowed */
272*4882a593Smuzhiyun 	return val >= COUNTER_OVERFLOW;
273*4882a593Smuzhiyun }
274*4882a593Smuzhiyun 
ebb_event_enable(struct event * e)275*4882a593Smuzhiyun int ebb_event_enable(struct event *e)
276*4882a593Smuzhiyun {
277*4882a593Smuzhiyun 	int rc;
278*4882a593Smuzhiyun 
279*4882a593Smuzhiyun 	/* Ensure any SPR writes are ordered vs us */
280*4882a593Smuzhiyun 	mb();
281*4882a593Smuzhiyun 
282*4882a593Smuzhiyun 	rc = ioctl(e->fd, PERF_EVENT_IOC_ENABLE);
283*4882a593Smuzhiyun 	if (rc)
284*4882a593Smuzhiyun 		return rc;
285*4882a593Smuzhiyun 
286*4882a593Smuzhiyun 	rc = event_read(e);
287*4882a593Smuzhiyun 
288*4882a593Smuzhiyun 	/* Ditto */
289*4882a593Smuzhiyun 	mb();
290*4882a593Smuzhiyun 
291*4882a593Smuzhiyun 	return rc;
292*4882a593Smuzhiyun }
293*4882a593Smuzhiyun 
ebb_freeze_pmcs(void)294*4882a593Smuzhiyun void ebb_freeze_pmcs(void)
295*4882a593Smuzhiyun {
296*4882a593Smuzhiyun 	mtspr(SPRN_MMCR0, mfspr(SPRN_MMCR0) | MMCR0_FC);
297*4882a593Smuzhiyun 	mb();
298*4882a593Smuzhiyun }
299*4882a593Smuzhiyun 
ebb_unfreeze_pmcs(void)300*4882a593Smuzhiyun void ebb_unfreeze_pmcs(void)
301*4882a593Smuzhiyun {
302*4882a593Smuzhiyun 	/* Unfreeze counters */
303*4882a593Smuzhiyun 	mtspr(SPRN_MMCR0, mfspr(SPRN_MMCR0) & ~MMCR0_FC);
304*4882a593Smuzhiyun 	mb();
305*4882a593Smuzhiyun }
306*4882a593Smuzhiyun 
ebb_global_enable(void)307*4882a593Smuzhiyun void ebb_global_enable(void)
308*4882a593Smuzhiyun {
309*4882a593Smuzhiyun 	/* Enable EBBs globally and PMU EBBs */
310*4882a593Smuzhiyun 	mtspr(SPRN_BESCR, 0x8000000100000000ull);
311*4882a593Smuzhiyun 	mb();
312*4882a593Smuzhiyun }
313*4882a593Smuzhiyun 
ebb_global_disable(void)314*4882a593Smuzhiyun void ebb_global_disable(void)
315*4882a593Smuzhiyun {
316*4882a593Smuzhiyun 	/* Disable EBBs & freeze counters, events are still scheduled */
317*4882a593Smuzhiyun 	mtspr(SPRN_BESCRR, BESCR_PME);
318*4882a593Smuzhiyun 	mb();
319*4882a593Smuzhiyun }
320*4882a593Smuzhiyun 
ebb_is_supported(void)321*4882a593Smuzhiyun bool ebb_is_supported(void)
322*4882a593Smuzhiyun {
323*4882a593Smuzhiyun #ifdef PPC_FEATURE2_EBB
324*4882a593Smuzhiyun 	/* EBB requires at least POWER8 */
325*4882a593Smuzhiyun 	return have_hwcap2(PPC_FEATURE2_EBB);
326*4882a593Smuzhiyun #else
327*4882a593Smuzhiyun 	return false;
328*4882a593Smuzhiyun #endif
329*4882a593Smuzhiyun }
330*4882a593Smuzhiyun 
event_ebb_init(struct event * e)331*4882a593Smuzhiyun void event_ebb_init(struct event *e)
332*4882a593Smuzhiyun {
333*4882a593Smuzhiyun 	e->attr.config |= (1ull << 63);
334*4882a593Smuzhiyun }
335*4882a593Smuzhiyun 
event_bhrb_init(struct event * e,unsigned ifm)336*4882a593Smuzhiyun void event_bhrb_init(struct event *e, unsigned ifm)
337*4882a593Smuzhiyun {
338*4882a593Smuzhiyun 	e->attr.config |= (1ull << 62) | ((u64)ifm << 60);
339*4882a593Smuzhiyun }
340*4882a593Smuzhiyun 
event_leader_ebb_init(struct event * e)341*4882a593Smuzhiyun void event_leader_ebb_init(struct event *e)
342*4882a593Smuzhiyun {
343*4882a593Smuzhiyun 	event_ebb_init(e);
344*4882a593Smuzhiyun 
345*4882a593Smuzhiyun 	e->attr.exclusive = 1;
346*4882a593Smuzhiyun 	e->attr.pinned = 1;
347*4882a593Smuzhiyun }
348*4882a593Smuzhiyun 
ebb_child(union pipe read_pipe,union pipe write_pipe)349*4882a593Smuzhiyun int ebb_child(union pipe read_pipe, union pipe write_pipe)
350*4882a593Smuzhiyun {
351*4882a593Smuzhiyun 	struct event event;
352*4882a593Smuzhiyun 	uint64_t val;
353*4882a593Smuzhiyun 
354*4882a593Smuzhiyun 	FAIL_IF(wait_for_parent(read_pipe));
355*4882a593Smuzhiyun 
356*4882a593Smuzhiyun 	event_init_named(&event, 0x1001e, "cycles");
357*4882a593Smuzhiyun 	event_leader_ebb_init(&event);
358*4882a593Smuzhiyun 
359*4882a593Smuzhiyun 	event.attr.exclude_kernel = 1;
360*4882a593Smuzhiyun 	event.attr.exclude_hv = 1;
361*4882a593Smuzhiyun 	event.attr.exclude_idle = 1;
362*4882a593Smuzhiyun 
363*4882a593Smuzhiyun 	FAIL_IF(event_open(&event));
364*4882a593Smuzhiyun 
365*4882a593Smuzhiyun 	ebb_enable_pmc_counting(1);
366*4882a593Smuzhiyun 	setup_ebb_handler(standard_ebb_callee);
367*4882a593Smuzhiyun 	ebb_global_enable();
368*4882a593Smuzhiyun 
369*4882a593Smuzhiyun 	FAIL_IF(event_enable(&event));
370*4882a593Smuzhiyun 
371*4882a593Smuzhiyun 	if (event_read(&event)) {
372*4882a593Smuzhiyun 		/*
373*4882a593Smuzhiyun 		 * Some tests expect to fail here, so don't report an error on
374*4882a593Smuzhiyun 		 * this line, and return a distinguisable error code. Tell the
375*4882a593Smuzhiyun 		 * parent an error happened.
376*4882a593Smuzhiyun 		 */
377*4882a593Smuzhiyun 		notify_parent_of_error(write_pipe);
378*4882a593Smuzhiyun 		return 2;
379*4882a593Smuzhiyun 	}
380*4882a593Smuzhiyun 
381*4882a593Smuzhiyun 	mtspr(SPRN_PMC1, pmc_sample_period(sample_period));
382*4882a593Smuzhiyun 
383*4882a593Smuzhiyun 	FAIL_IF(notify_parent(write_pipe));
384*4882a593Smuzhiyun 	FAIL_IF(wait_for_parent(read_pipe));
385*4882a593Smuzhiyun 	FAIL_IF(notify_parent(write_pipe));
386*4882a593Smuzhiyun 
387*4882a593Smuzhiyun 	while (ebb_state.stats.ebb_count < 20) {
388*4882a593Smuzhiyun 		FAIL_IF(core_busy_loop());
389*4882a593Smuzhiyun 
390*4882a593Smuzhiyun 		/* To try and hit SIGILL case */
391*4882a593Smuzhiyun 		val  = mfspr(SPRN_MMCRA);
392*4882a593Smuzhiyun 		val |= mfspr(SPRN_MMCR2);
393*4882a593Smuzhiyun 		val |= mfspr(SPRN_MMCR0);
394*4882a593Smuzhiyun 	}
395*4882a593Smuzhiyun 
396*4882a593Smuzhiyun 	ebb_global_disable();
397*4882a593Smuzhiyun 	ebb_freeze_pmcs();
398*4882a593Smuzhiyun 
399*4882a593Smuzhiyun 	dump_ebb_state();
400*4882a593Smuzhiyun 
401*4882a593Smuzhiyun 	event_close(&event);
402*4882a593Smuzhiyun 
403*4882a593Smuzhiyun 	FAIL_IF(ebb_state.stats.ebb_count == 0);
404*4882a593Smuzhiyun 
405*4882a593Smuzhiyun 	return 0;
406*4882a593Smuzhiyun }
407*4882a593Smuzhiyun 
408*4882a593Smuzhiyun static jmp_buf setjmp_env;
409*4882a593Smuzhiyun 
sigill_handler(int signal)410*4882a593Smuzhiyun static void sigill_handler(int signal)
411*4882a593Smuzhiyun {
412*4882a593Smuzhiyun 	printf("Took sigill\n");
413*4882a593Smuzhiyun 	longjmp(setjmp_env, 1);
414*4882a593Smuzhiyun }
415*4882a593Smuzhiyun 
416*4882a593Smuzhiyun static struct sigaction sigill_action = {
417*4882a593Smuzhiyun 	.sa_handler = sigill_handler,
418*4882a593Smuzhiyun };
419*4882a593Smuzhiyun 
catch_sigill(void (* func)(void))420*4882a593Smuzhiyun int catch_sigill(void (*func)(void))
421*4882a593Smuzhiyun {
422*4882a593Smuzhiyun 	if (sigaction(SIGILL, &sigill_action, NULL)) {
423*4882a593Smuzhiyun 		perror("sigaction");
424*4882a593Smuzhiyun 		return 1;
425*4882a593Smuzhiyun 	}
426*4882a593Smuzhiyun 
427*4882a593Smuzhiyun 	if (setjmp(setjmp_env) == 0) {
428*4882a593Smuzhiyun 		func();
429*4882a593Smuzhiyun 		return 1;
430*4882a593Smuzhiyun 	}
431*4882a593Smuzhiyun 
432*4882a593Smuzhiyun 	return 0;
433*4882a593Smuzhiyun }
434*4882a593Smuzhiyun 
write_pmc1(void)435*4882a593Smuzhiyun void write_pmc1(void)
436*4882a593Smuzhiyun {
437*4882a593Smuzhiyun 	mtspr(SPRN_PMC1, 0);
438*4882a593Smuzhiyun }
439*4882a593Smuzhiyun 
write_pmc(int pmc,u64 value)440*4882a593Smuzhiyun void write_pmc(int pmc, u64 value)
441*4882a593Smuzhiyun {
442*4882a593Smuzhiyun 	switch (pmc) {
443*4882a593Smuzhiyun 		case 1: mtspr(SPRN_PMC1, value); break;
444*4882a593Smuzhiyun 		case 2: mtspr(SPRN_PMC2, value); break;
445*4882a593Smuzhiyun 		case 3: mtspr(SPRN_PMC3, value); break;
446*4882a593Smuzhiyun 		case 4: mtspr(SPRN_PMC4, value); break;
447*4882a593Smuzhiyun 		case 5: mtspr(SPRN_PMC5, value); break;
448*4882a593Smuzhiyun 		case 6: mtspr(SPRN_PMC6, value); break;
449*4882a593Smuzhiyun 	}
450*4882a593Smuzhiyun }
451*4882a593Smuzhiyun 
read_pmc(int pmc)452*4882a593Smuzhiyun u64 read_pmc(int pmc)
453*4882a593Smuzhiyun {
454*4882a593Smuzhiyun 	switch (pmc) {
455*4882a593Smuzhiyun 		case 1: return mfspr(SPRN_PMC1);
456*4882a593Smuzhiyun 		case 2: return mfspr(SPRN_PMC2);
457*4882a593Smuzhiyun 		case 3: return mfspr(SPRN_PMC3);
458*4882a593Smuzhiyun 		case 4: return mfspr(SPRN_PMC4);
459*4882a593Smuzhiyun 		case 5: return mfspr(SPRN_PMC5);
460*4882a593Smuzhiyun 		case 6: return mfspr(SPRN_PMC6);
461*4882a593Smuzhiyun 	}
462*4882a593Smuzhiyun 
463*4882a593Smuzhiyun 	return 0;
464*4882a593Smuzhiyun }
465*4882a593Smuzhiyun 
term_handler(int signal)466*4882a593Smuzhiyun static void term_handler(int signal)
467*4882a593Smuzhiyun {
468*4882a593Smuzhiyun 	dump_summary_ebb_state();
469*4882a593Smuzhiyun 	dump_ebb_hw_state();
470*4882a593Smuzhiyun 	abort();
471*4882a593Smuzhiyun }
472*4882a593Smuzhiyun 
473*4882a593Smuzhiyun struct sigaction term_action = {
474*4882a593Smuzhiyun 	.sa_handler = term_handler,
475*4882a593Smuzhiyun };
476*4882a593Smuzhiyun 
ebb_init(void)477*4882a593Smuzhiyun static void __attribute__((constructor)) ebb_init(void)
478*4882a593Smuzhiyun {
479*4882a593Smuzhiyun 	clear_ebb_stats();
480*4882a593Smuzhiyun 
481*4882a593Smuzhiyun 	if (sigaction(SIGTERM, &term_action, NULL))
482*4882a593Smuzhiyun 		perror("sigaction");
483*4882a593Smuzhiyun 
484*4882a593Smuzhiyun 	ebb_state.trace = trace_buffer_allocate(1 * 1024 * 1024);
485*4882a593Smuzhiyun }
486