1/* 2 * Copyright 2014, Michael Ellerman, IBM Corp. 3 * Licensed under GPLv2. 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 27static 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 43out: 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 62int 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 count_pmc(1, sample_period); 95 96 dump_ebb_state(); 97 98 event_close(&event); 99 100 FAIL_IF(ebb_state.stats.ebb_count != NUMBER_OF_EBBS); 101 102 return 0; 103} 104 105int main(void) 106{ 107 return test_harness(back_to_back_ebbs, "back_to_back_ebbs"); 108} 109