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 event_init_named(&event, 0x1001e, "cycles"); 67 event_leader_ebb_init(&event); 68 69 event.attr.exclude_kernel = 1; 70 event.attr.exclude_hv = 1; 71 event.attr.exclude_idle = 1; 72 73 FAIL_IF(event_open(&event)); 74 75 setup_ebb_handler(ebb_callee); 76 77 FAIL_IF(ebb_event_enable(&event)); 78 79 sample_period = 5; 80 81 ebb_freeze_pmcs(); 82 mtspr(SPRN_PMC1, pmc_sample_period(sample_period)); 83 ebb_global_enable(); 84 ebb_unfreeze_pmcs(); 85 86 while (ebb_state.stats.ebb_count < NUMBER_OF_EBBS) 87 FAIL_IF(core_busy_loop()); 88 89 ebb_global_disable(); 90 ebb_freeze_pmcs(); 91 92 count_pmc(1, sample_period); 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 103int main(void) 104{ 105 return test_harness(back_to_back_ebbs, "back_to_back_ebbs"); 106} 107