1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright 2014, Michael Ellerman, IBM Corp. 4 */ 5 6 #include <stdbool.h> 7 #include <stdio.h> 8 #include <stdlib.h> 9 10 #include "ebb.h" 11 12 13 #define NUMBER_OF_EBBS 50 14 15 /* 16 * Test that if we overflow the counter while in the EBB handler, we take 17 * another EBB on exiting from the handler. 18 * 19 * We do this by counting with a stupidly low sample period, causing us to 20 * overflow the PMU while we're still in the EBB handler, leading to another 21 * EBB. 22 * 23 * We get out of what would otherwise be an infinite loop by leaving the 24 * counter frozen once we've taken enough EBBs. 25 */ 26 27 static void ebb_callee(void) 28 { 29 uint64_t siar, val; 30 31 val = mfspr(SPRN_BESCR); 32 if (!(val & BESCR_PMEO)) { 33 ebb_state.stats.spurious++; 34 goto out; 35 } 36 37 ebb_state.stats.ebb_count++; 38 trace_log_counter(ebb_state.trace, ebb_state.stats.ebb_count); 39 40 /* Resets the PMC */ 41 count_pmc(1, sample_period); 42 43 out: 44 if (ebb_state.stats.ebb_count == NUMBER_OF_EBBS) 45 /* Reset but leave counters frozen */ 46 reset_ebb_with_clear_mask(MMCR0_PMAO); 47 else 48 /* Unfreezes */ 49 reset_ebb(); 50 51 /* Do some stuff to chew some cycles and pop the counter */ 52 siar = mfspr(SPRN_SIAR); 53 trace_log_reg(ebb_state.trace, SPRN_SIAR, siar); 54 55 val = mfspr(SPRN_PMC1); 56 trace_log_reg(ebb_state.trace, SPRN_PMC1, val); 57 58 val = mfspr(SPRN_MMCR0); 59 trace_log_reg(ebb_state.trace, SPRN_MMCR0, val); 60 } 61 62 int back_to_back_ebbs(void) 63 { 64 struct event event; 65 66 SKIP_IF(!ebb_is_supported()); 67 68 event_init_named(&event, 0x1001e, "cycles"); 69 event_leader_ebb_init(&event); 70 71 event.attr.exclude_kernel = 1; 72 event.attr.exclude_hv = 1; 73 event.attr.exclude_idle = 1; 74 75 FAIL_IF(event_open(&event)); 76 77 setup_ebb_handler(ebb_callee); 78 79 FAIL_IF(ebb_event_enable(&event)); 80 81 sample_period = 5; 82 83 ebb_freeze_pmcs(); 84 mtspr(SPRN_PMC1, pmc_sample_period(sample_period)); 85 ebb_global_enable(); 86 ebb_unfreeze_pmcs(); 87 88 while (ebb_state.stats.ebb_count < NUMBER_OF_EBBS) 89 FAIL_IF(core_busy_loop()); 90 91 ebb_global_disable(); 92 ebb_freeze_pmcs(); 93 94 dump_ebb_state(); 95 96 event_close(&event); 97 98 FAIL_IF(ebb_state.stats.ebb_count != NUMBER_OF_EBBS); 99 100 return 0; 101 } 102 103 int main(void) 104 { 105 return test_harness(back_to_back_ebbs, "back_to_back_ebbs"); 106 } 107
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.