]>
git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blob - tools/testing/selftests/powerpc/pmu/ebb/ebb.c
1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright 2014, Michael Ellerman, IBM Corp.
6 #define _GNU_SOURCE /* For CPU_ZERO etc. */
15 #include <sys/ioctl.h>
21 void (*ebb_user_func
)(void);
29 struct ebb_state ebb_state
;
31 u64 sample_period
= 0x40000000ull
;
33 void reset_ebb_with_clear_mask(unsigned long mmcr0_clear_mask
)
37 /* 2) clear MMCR0[PMAO] - docs say BESCR[PMEO] should do this */
38 /* 3) set MMCR0[PMAE] - docs say BESCR[PME] should do this */
39 val
= mfspr(SPRN_MMCR0
);
40 mtspr(SPRN_MMCR0
, (val
& ~mmcr0_clear_mask
) | MMCR0_PMAE
);
42 /* 4) clear BESCR[PMEO] */
43 mtspr(SPRN_BESCRR
, BESCR_PMEO
);
45 /* 5) set BESCR[PME] */
46 mtspr(SPRN_BESCRS
, BESCR_PME
);
48 /* 6) rfebb 1 - done in our caller */
53 reset_ebb_with_clear_mask(MMCR0_PMAO
| MMCR0_FC
);
56 /* Called outside of the EBB handler to check MMCR0 is sane */
57 int ebb_check_mmcr0(void)
61 val
= mfspr(SPRN_MMCR0
);
62 if ((val
& (MMCR0_FC
| MMCR0_PMAO
)) == MMCR0_FC
) {
63 /* It's OK if we see FC & PMAO, but not FC by itself */
64 printf("Outside of loop, only FC set 0x%llx\n", val
);
71 bool ebb_check_count(int pmc
, u64 sample_period
, int fudge
)
73 u64 count
, upper
, lower
;
75 count
= ebb_state
.stats
.pmc_count
[PMC_INDEX(pmc
)];
77 lower
= ebb_state
.stats
.ebb_count
* (sample_period
- fudge
);
80 printf("PMC%d count (0x%llx) below lower limit 0x%llx (-0x%llx)\n",
81 pmc
, count
, lower
, lower
- count
);
85 upper
= ebb_state
.stats
.ebb_count
* (sample_period
+ fudge
);
88 printf("PMC%d count (0x%llx) above upper limit 0x%llx (+0x%llx)\n",
89 pmc
, count
, upper
, count
- upper
);
93 printf("PMC%d count (0x%llx) is between 0x%llx and 0x%llx delta +0x%llx/-0x%llx\n",
94 pmc
, count
, lower
, upper
, count
- lower
, upper
- count
);
99 void standard_ebb_callee(void)
104 val
= mfspr(SPRN_BESCR
);
105 if (!(val
& BESCR_PMEO
)) {
106 ebb_state
.stats
.spurious
++;
110 ebb_state
.stats
.ebb_count
++;
111 trace_log_counter(ebb_state
.trace
, ebb_state
.stats
.ebb_count
);
113 val
= mfspr(SPRN_MMCR0
);
114 trace_log_reg(ebb_state
.trace
, SPRN_MMCR0
, val
);
117 for (i
= 1; i
<= 6; i
++) {
118 if (ebb_state
.pmc_enable
[PMC_INDEX(i
)])
119 found
+= count_pmc(i
, sample_period
);
123 ebb_state
.stats
.no_overflow
++;
129 extern void ebb_handler(void);
131 void setup_ebb_handler(void (*callee
)(void))
135 #if defined(_CALL_ELF) && _CALL_ELF == 2
136 entry
= (u64
)ebb_handler
;
144 opd
= (struct opd
*)ebb_handler
;
147 printf("EBB Handler is at %#llx\n", entry
);
149 ebb_user_func
= callee
;
151 /* Ensure ebb_user_func is set before we set the handler */
153 mtspr(SPRN_EBBHR
, entry
);
155 /* Make sure the handler is set before we return */
159 void clear_ebb_stats(void)
161 memset(&ebb_state
.stats
, 0, sizeof(ebb_state
.stats
));
164 void dump_summary_ebb_state(void)
166 printf("ebb_state:\n" \
167 " ebb_count = %d\n" \
170 " no_overflow = %d\n" \
171 " pmc[1] count = 0x%llx\n" \
172 " pmc[2] count = 0x%llx\n" \
173 " pmc[3] count = 0x%llx\n" \
174 " pmc[4] count = 0x%llx\n" \
175 " pmc[5] count = 0x%llx\n" \
176 " pmc[6] count = 0x%llx\n",
177 ebb_state
.stats
.ebb_count
, ebb_state
.stats
.spurious
,
178 ebb_state
.stats
.negative
, ebb_state
.stats
.no_overflow
,
179 ebb_state
.stats
.pmc_count
[0], ebb_state
.stats
.pmc_count
[1],
180 ebb_state
.stats
.pmc_count
[2], ebb_state
.stats
.pmc_count
[3],
181 ebb_state
.stats
.pmc_count
[4], ebb_state
.stats
.pmc_count
[5]);
184 static char *decode_mmcr0(u32 value
)
190 if (value
& (1 << 31))
192 if (value
& (1 << 26))
193 strcat(buf
, "PMAE ");
194 if (value
& (1 << 7))
195 strcat(buf
, "PMAO ");
200 static char *decode_bescr(u64 value
)
206 if (value
& (1ull << 63))
208 if (value
& (1ull << 32))
209 strcat(buf
, "PMAE ");
211 strcat(buf
, "PMAO ");
216 void dump_ebb_hw_state(void)
221 mmcr0
= mfspr(SPRN_MMCR0
);
222 bescr
= mfspr(SPRN_BESCR
);
224 printf("HW state:\n" \
225 "MMCR0 0x%016x %s\n" \
228 "BESCR 0x%016llx %s\n" \
236 mmcr0
, decode_mmcr0(mmcr0
), mfspr(SPRN_MMCR2
),
237 mfspr(SPRN_EBBHR
), bescr
, decode_bescr(bescr
),
238 mfspr(SPRN_PMC1
), mfspr(SPRN_PMC2
), mfspr(SPRN_PMC3
),
239 mfspr(SPRN_PMC4
), mfspr(SPRN_PMC5
), mfspr(SPRN_PMC6
),
243 void dump_ebb_state(void)
245 dump_summary_ebb_state();
249 trace_buffer_print(ebb_state
.trace
);
252 int count_pmc(int pmc
, uint32_t sample_period
)
254 uint32_t start_value
;
258 start_value
= pmc_sample_period(sample_period
);
261 if (val
< start_value
)
262 ebb_state
.stats
.negative
++;
264 ebb_state
.stats
.pmc_count
[PMC_INDEX(pmc
)] += val
- start_value
;
266 trace_log_reg(ebb_state
.trace
, SPRN_PMC1
+ pmc
- 1, val
);
269 write_pmc(pmc
, start_value
);
271 /* Report if we overflowed */
272 return val
>= COUNTER_OVERFLOW
;
275 int ebb_event_enable(struct event
*e
)
279 /* Ensure any SPR writes are ordered vs us */
282 rc
= ioctl(e
->fd
, PERF_EVENT_IOC_ENABLE
);
294 void ebb_freeze_pmcs(void)
296 mtspr(SPRN_MMCR0
, mfspr(SPRN_MMCR0
) | MMCR0_FC
);
300 void ebb_unfreeze_pmcs(void)
302 /* Unfreeze counters */
303 mtspr(SPRN_MMCR0
, mfspr(SPRN_MMCR0
) & ~MMCR0_FC
);
307 void ebb_global_enable(void)
309 /* Enable EBBs globally and PMU EBBs */
310 mtspr(SPRN_BESCR
, 0x8000000100000000ull
);
314 void ebb_global_disable(void)
316 /* Disable EBBs & freeze counters, events are still scheduled */
317 mtspr(SPRN_BESCRR
, BESCR_PME
);
321 bool ebb_is_supported(void)
323 #ifdef PPC_FEATURE2_EBB
324 /* EBB requires at least POWER8 */
325 return have_hwcap2(PPC_FEATURE2_EBB
);
331 void event_ebb_init(struct event
*e
)
333 e
->attr
.config
|= (1ull << 63);
336 void event_bhrb_init(struct event
*e
, unsigned ifm
)
338 e
->attr
.config
|= (1ull << 62) | ((u64
)ifm
<< 60);
341 void event_leader_ebb_init(struct event
*e
)
345 e
->attr
.exclusive
= 1;
349 int ebb_child(union pipe read_pipe
, union pipe write_pipe
)
354 FAIL_IF(wait_for_parent(read_pipe
));
356 event_init_named(&event
, 0x1001e, "cycles");
357 event_leader_ebb_init(&event
);
359 event
.attr
.exclude_kernel
= 1;
360 event
.attr
.exclude_hv
= 1;
361 event
.attr
.exclude_idle
= 1;
363 FAIL_IF(event_open(&event
));
365 ebb_enable_pmc_counting(1);
366 setup_ebb_handler(standard_ebb_callee
);
369 FAIL_IF(event_enable(&event
));
371 if (event_read(&event
)) {
373 * Some tests expect to fail here, so don't report an error on
374 * this line, and return a distinguisable error code. Tell the
375 * parent an error happened.
377 notify_parent_of_error(write_pipe
);
381 mtspr(SPRN_PMC1
, pmc_sample_period(sample_period
));
383 FAIL_IF(notify_parent(write_pipe
));
384 FAIL_IF(wait_for_parent(read_pipe
));
385 FAIL_IF(notify_parent(write_pipe
));
387 while (ebb_state
.stats
.ebb_count
< 20) {
388 FAIL_IF(core_busy_loop());
390 /* To try and hit SIGILL case */
391 val
= mfspr(SPRN_MMCRA
);
392 val
|= mfspr(SPRN_MMCR2
);
393 val
|= mfspr(SPRN_MMCR0
);
396 ebb_global_disable();
399 count_pmc(1, sample_period
);
405 FAIL_IF(ebb_state
.stats
.ebb_count
== 0);
410 static jmp_buf setjmp_env
;
412 static void sigill_handler(int signal
)
414 printf("Took sigill\n");
415 longjmp(setjmp_env
, 1);
418 static struct sigaction sigill_action
= {
419 .sa_handler
= sigill_handler
,
422 int catch_sigill(void (*func
)(void))
424 if (sigaction(SIGILL
, &sigill_action
, NULL
)) {
429 if (setjmp(setjmp_env
) == 0) {
437 void write_pmc1(void)
442 void write_pmc(int pmc
, u64 value
)
445 case 1: mtspr(SPRN_PMC1
, value
); break;
446 case 2: mtspr(SPRN_PMC2
, value
); break;
447 case 3: mtspr(SPRN_PMC3
, value
); break;
448 case 4: mtspr(SPRN_PMC4
, value
); break;
449 case 5: mtspr(SPRN_PMC5
, value
); break;
450 case 6: mtspr(SPRN_PMC6
, value
); break;
454 u64
read_pmc(int pmc
)
457 case 1: return mfspr(SPRN_PMC1
);
458 case 2: return mfspr(SPRN_PMC2
);
459 case 3: return mfspr(SPRN_PMC3
);
460 case 4: return mfspr(SPRN_PMC4
);
461 case 5: return mfspr(SPRN_PMC5
);
462 case 6: return mfspr(SPRN_PMC6
);
468 static void term_handler(int signal
)
470 dump_summary_ebb_state();
475 struct sigaction term_action
= {
476 .sa_handler
= term_handler
,
479 static void __attribute__((constructor
)) ebb_init(void)
483 if (sigaction(SIGTERM
, &term_action
, NULL
))
486 ebb_state
.trace
= trace_buffer_allocate(1 * 1024 * 1024);