/*************************************************************************** * Copyright (c) 2006-2007, Broadcom Corporation * All Rights Reserved * Confidential Property of Broadcom Corporation * * THIS SOFTWARE MAY ONLY BE USED SUBJECT TO AN EXECUTED SOFTWARE LICENSE * AGREEMENT BETWEEN THE USER AND BROADCOM. YOU HAVE NO RIGHT TO USE OR * EXPLOIT THIS MATERIAL EXCEPT SUBJECT TO THE TERMS OF SUCH AN AGREEMENT. * * $brcm_Workfile: bperf_counter.c $ * $brcm_Revision: 8 $ * $brcm_Date: 1/15/07 10:50a $ * * Module Description: * * Perfomance counter module * * Revision History: * * $brcm_Log: /BSEAV/lib/bprofile/bperf_counter.c $ * * 8 1/15/07 10:50a vsilyaev * PR 25997: Added 7038 performance counters * * 7 12/22/06 12:03p vsilyaev * PR 26792: Added rac_access, rac_prefetch and rac_hits configurations * for the peformance counter * * 6 12/14/06 4:38p vsilyaev * PR 25997: Added counter configuration to capture issue rate * * 5 12/13/06 7:46p vsilyaev * PR 25997: Removed debug output * * 4 12/8/06 7:24p vsilyaev * PR 25997: Fixed warning * * 3 12/7/06 2:44p vsilyaev * PR 25997: Added fixes for 3.4 GCC compiler * * 2 12/5/06 11:08a vsilyaev * PR 25997: Improved perf counter interface * * 1 12/1/06 5:58p vsilyaev * PR 25997: CPU perfomance counter interface * * *******************************************************************************/ #include "bstd.h" #include "bkni.h" #include "bperf_counter.h" #include "biobits.h" BDBG_MODULE(bperf_counter); static const char b_insructions[] = "Instructions"; static const char b_cycles[] = "Cycles"; static const char b_dcache_miss[]= "D-Cache miss"; #if B_PERF_BMIPS3300 /* bcmips3300-arch.pdf pages 63..66 */ #define B_ICACHE_MOD_ID 0x06 #define B_ICACHE_ID 0x00 #define B_ICACHE_HIT 0x06 #define B_ICACHE_MISS 0x05 #define B_DCACHE_MOD_ID 0x04 #define B_DCACHE_ID 0x01 #define B_DCACHE_HIT 0x0A #define B_DCACHE_MISS 0x09 #define B_RAC_MOD_ID 0x0B #define B_RAC_ACCESS_ID 0x00 #define B_RAC_ACCESS 0x42 #define B_RAC_PREFETCH_ID 0x01 #define B_RAC_PREFETCH 0x4B #define B_BIU_MOD_ID 0x01 #define B_RAC_HIT_ID 0x02 #define B_RAC_HIT 0x45 #define B_CYCLES 0x12 #define B_INSTRUCTIONS 0x11 const bperf_counter_mode bperf_counter_dcache = { { b_dcache_miss, "D-Cache hit", b_insructions, b_cycles }, { /* $25 #6 */ B_SET_BIT(PCE, 1 /* enable */, 31) | B_SET_BIT(magic, 1 /* enable */, 9) | B_SET_BIT(PCSD, 0 /* enable */, 8) | B_SET_BITS(ModID, B_DCACHE_MOD_ID, 5, 2) | B_SET_BITS(SetID, B_DCACHE_ID, 1, 0), /* $25 #4 */ B_SET_BIT(CE, 1 /* enable */, 15) | B_SET_BITS(EVT, B_DCACHE_MISS, 8, 2) | B_SET_BIT(TIE, 0 /* disable */, 0) | B_SET_BIT(CE, 1 /* enable */, 15+16) | B_SET_BITS(EVT, B_DCACHE_HIT, 8+16, 2+16) | B_SET_BIT(TIE, 0 /* disable */, 0+16), /* $25 #5 */ B_SET_BIT(CE, 1 /* enable */, 15) | B_SET_BITS(EVT, B_INSTRUCTIONS, 8, 2) | B_SET_BIT(TIE, 0 /* disable */, 0) | B_SET_BIT(CE, 1 /* enable */, 15+16) | B_SET_BITS(EVT, B_CYCLES, 8+16, 2+16) | B_SET_BIT(TIE, 0 /* disable */, 0+16) } }; const bperf_counter_mode bperf_counter_instructions = { { b_insructions, b_dcache_miss, b_insructions, b_cycles }, { /* $25 #6 */ B_SET_BIT(PCE, 1 /* enable */, 31) | B_SET_BIT(magic, 1 /* enable */, 9) | B_SET_BIT(PCSD, 0 /* enable */, 8) | B_SET_BITS(ModID, B_DCACHE_MOD_ID, 5, 2) | B_SET_BITS(SetID, B_DCACHE_ID, 1, 0), /* $25 #4 */ B_SET_BIT(CE, 1 /* enable */, 15) | B_SET_BITS(EVT, B_INSTRUCTIONS, 8, 2) | B_SET_BIT(TIE, 0 /* disable */, 0) | B_SET_BIT(CE, 1 /* enable */, 15+16) | B_SET_BITS(EVT, B_DCACHE_MISS, 8+16, 2+16) | B_SET_BIT(TIE, 0 /* disable */, 0+16), /* $25 #5 */ B_SET_BIT(CE, 1 /* enable */, 15) | B_SET_BITS(EVT, B_INSTRUCTIONS, 8, 2) | B_SET_BIT(TIE, 0 /* disable */, 0) | B_SET_BIT(CE, 1 /* enable */, 15+16) | B_SET_BITS(EVT, B_CYCLES, 8+16, 2+16) | B_SET_BIT(TIE, 0 /* disable */, 0+16) } }; const bperf_counter_mode bperf_counter_icache = { { "I-Cache miss", "I-Cache hit", b_insructions, b_cycles }, { /* $25 #6 */ B_SET_BIT(PCE, 1 /* enable */, 31) | B_SET_BIT(magic, 1 /* enable */, 9) | B_SET_BIT(PCSD, 0 /* enable */, 8) | B_SET_BITS(ModID, B_ICACHE_MOD_ID, 5, 2) | B_SET_BITS(SetID, B_ICACHE_ID, 1, 0), /* $25 #4 */ B_SET_BIT(CE, 1 /* enable */, 15) | B_SET_BITS(EVT, B_ICACHE_MISS, 8, 2) | B_SET_BIT(TIE, 0 /* disable */, 0) | B_SET_BIT(CE, 1 /* enable */, 15+16) | B_SET_BITS(EVT, B_ICACHE_HIT, 8+16, 2+16) | B_SET_BIT(TIE, 0 /* disable */, 0+16), /* $25 #5 */ B_SET_BIT(CE, 1 /* enable */, 15) | B_SET_BITS(EVT, B_INSTRUCTIONS, 8, 2) | B_SET_BIT(TIE, 0 /* disable */, 0) | B_SET_BIT(CE, 1 /* enable */, 15+16) | B_SET_BITS(EVT, B_CYCLES, 8+16, 2+16) | B_SET_BIT(TIE, 0 /* disable */, 0+16) } }; const bperf_counter_mode bperf_counter_rac_access = { { "RAC access", b_insructions, b_insructions, b_cycles }, { /* $25 #6 */ B_SET_BIT(PCE, 1 /* enable */, 31) | B_SET_BIT(magic, 1 /* enable */, 9) | B_SET_BIT(PCSD, 0 /* enable */, 8) | B_SET_BITS(ModID, B_RAC_MOD_ID, 5, 2) | B_SET_BITS(SetID, B_RAC_ACCESS_ID, 1, 0), /* $25 #4 */ B_SET_BIT(CE, 1 /* enable */, 15) | B_SET_BITS(EVT, B_RAC_ACCESS, 8, 2) | B_SET_BIT(TIE, 0 /* disable */, 0) | B_SET_BIT(CE, 1 /* enable */, 15+16) | B_SET_BITS(EVT, B_INSTRUCTIONS, 8+16, 2+16) | B_SET_BIT(TIE, 0 /* disable */, 0+16), /* $25 #5 */ B_SET_BIT(CE, 1 /* enable */, 15) | B_SET_BITS(EVT, B_INSTRUCTIONS, 8, 2) | B_SET_BIT(TIE, 0 /* disable */, 0) | B_SET_BIT(CE, 1 /* enable */, 15+16) | B_SET_BITS(EVT, B_CYCLES, 8+16, 2+16) | B_SET_BIT(TIE, 0 /* disable */, 0+16) } }; const bperf_counter_mode bperf_counter_rac_prefetch = { { "RAC prefetch", b_insructions, b_insructions, b_cycles }, { /* $25 #6 */ B_SET_BIT(PCE, 1 /* enable */, 31) | B_SET_BIT(magic, 1 /* enable */, 9) | B_SET_BIT(PCSD, 0 /* enable */, 8) | B_SET_BITS(ModID, B_RAC_MOD_ID, 5, 2) | B_SET_BITS(SetID, B_RAC_PREFETCH_ID, 1, 0), /* $25 #4 */ B_SET_BIT(CE, 1 /* enable */, 15) | B_SET_BITS(EVT, B_RAC_PREFETCH, 8, 2) | B_SET_BIT(TIE, 0 /* disable */, 0) | B_SET_BIT(CE, 1 /* enable */, 15+16) | B_SET_BITS(EVT, B_INSTRUCTIONS, 8+16, 2+16) | B_SET_BIT(TIE, 0 /* disable */, 0+16), /* $25 #5 */ B_SET_BIT(CE, 1 /* enable */, 15) | B_SET_BITS(EVT, B_INSTRUCTIONS, 8, 2) | B_SET_BIT(TIE, 0 /* disable */, 0) | B_SET_BIT(CE, 1 /* enable */, 15+16) | B_SET_BITS(EVT, B_CYCLES, 8+16, 2+16) | B_SET_BIT(TIE, 0 /* disable */, 0+16) } }; const bperf_counter_mode bperf_counter_rac_hit = { { "RAC hits", b_insructions, b_insructions, b_cycles }, { /* $25 #6 */ B_SET_BIT(PCE, 1 /* enable */, 31) | B_SET_BIT(magic, 1 /* enable */, 9) | B_SET_BIT(PCSD, 0 /* enable */, 8) | B_SET_BITS(ModID, B_BIU_MOD_ID, 5, 2) | B_SET_BITS(SetID, B_RAC_HIT_ID, 1, 0), /* $25 #4 */ B_SET_BIT(CE, 1 /* enable */, 15) | B_SET_BITS(EVT, B_RAC_HIT, 8, 2) | B_SET_BIT(TIE, 0 /* disable */, 0) | B_SET_BIT(CE, 1 /* enable */, 15+16) | B_SET_BITS(EVT, B_INSTRUCTIONS, 8+16, 2+16) | B_SET_BIT(TIE, 0 /* disable */, 0+16), /* $25 #5 */ B_SET_BIT(CE, 1 /* enable */, 15) | B_SET_BITS(EVT, B_INSTRUCTIONS, 8, 2) | B_SET_BIT(TIE, 0 /* disable */, 0) | B_SET_BIT(CE, 1 /* enable */, 15+16) | B_SET_BITS(EVT, B_CYCLES, 8+16, 2+16) | B_SET_BIT(TIE, 0 /* disable */, 0+16) } }; #elif B_PERF_MIPSR5K /* MD00012-2B-5K-SUM-02.08.pdf pages 146..150 */ #define B_EVENT_CYCLES 0 #define B_EVENT_0_INST_FETCHED 1 #define B_EVENT_1_INST_EXECUTED 1 #define B_EVENT_CACHE_OPS 2 #define B_EVENT_STORES 3 #define B_EVENT_COND_STORES 4 #define B_EVENT_0_FAIL_STORES 5 #define B_EVENT_1_FPU_OPS 5 #define B_EVENT_0_BRANCHES 6 #define B_EVENT_1_DCACHE_EVICTED 6 #define B_EVENT_0_ITLB_MISS 7 #define B_EVENT_1_TLB_MISS_EXC 7 #define B_EVENT_0_DTLB_MISS 8 #define B_EVENT_1_BRANCH_MISS 8 #define B_EVENT_0_ICACHE_MISS 9 #define B_EVENT_1_DCACHE_MISS 9 #define B_EVENT_0_INST_SCHED 10 #define B_EVENT_1_INST_STALL 10 #define B_EVENT_0_DUAL_ISSUE 14 #define B_EVENT_0_INST_EXECUTED 15 #define B_EVENT_1_INST_COP2 15 const bperf_counter_mode bperf_counter_dcache = { { "I-Cache miss", b_dcache_miss }, { /* $25 0 */ B_SET_BITS(Event, B_EVENT_0_ICACHE_MISS, 8, 5) | B_SET_BIT(IE, 1, 4) | B_SET_BIT(U, 1, 3) | B_SET_BIT(S, 1, 2) | B_SET_BIT(K, 1, 1) | B_SET_BIT(EXL, 1, 0), /* $25 2 */ B_SET_BITS(Event, B_EVENT_1_DCACHE_MISS, 8, 5) | B_SET_BIT(IE, 1, 4) | B_SET_BIT(U, 1, 3) | B_SET_BIT(S, 1, 2) | B_SET_BIT(K, 1, 1) | B_SET_BIT(EXL, 1, 0), /* unused */ 0 } }; const bperf_counter_mode bperf_counter_icache = { { "I-Cache miss", b_dcache_miss }, { /* $25 0 */ B_SET_BITS(Event, B_EVENT_0_ICACHE_MISS, 8, 5) | B_SET_BIT(IE, 1, 4) | B_SET_BIT(U, 1, 3) | B_SET_BIT(S, 1, 2) | B_SET_BIT(K, 1, 1) | B_SET_BIT(EXL, 1, 0), /* $25 2 */ B_SET_BITS(Event, B_EVENT_1_DCACHE_MISS, 8, 5) | B_SET_BIT(IE, 1, 4) | B_SET_BIT(U, 1, 3) | B_SET_BIT(S, 1, 2) | B_SET_BIT(K, 1, 1) | B_SET_BIT(EXL, 1, 0), /* unused */ 0 } }; const bperf_counter_mode bperf_counter_instructions = { { b_insructions, b_cycles }, { /* $25 0 */ B_SET_BITS(Event, B_EVENT_0_INST_EXECUTED, 8, 5) | B_SET_BIT(IE, 1, 4) | B_SET_BIT(U, 1, 3) | B_SET_BIT(S, 1, 2) | B_SET_BIT(K, 1, 1) | B_SET_BIT(EXL, 1, 0), /* $25 2 */ B_SET_BITS(Event, B_EVENT_CYCLES, 8, 5) | B_SET_BIT(IE, 1, 4) | B_SET_BIT(U, 1, 3) | B_SET_BIT(S, 1, 2) | B_SET_BIT(K, 1, 1) | B_SET_BIT(EXL, 1, 0), /* unused */ 0 } }; #endif static const bperf_counter_mode *b_perf_mode = NULL; #define bcm_write_perf(sel, value) \ { __asm__ __volatile__(".set\tpush\n\t" \ ".set\tmips32\n\t" \ "mtc0\t%0, $25, " #sel "\n\t" \ ".set\tpop\n\t" \ : /* none */ \ : "r" ((unsigned int)value)); \ } int b_perf_init(const bperf_counter_mode *mode) { BDBG_ASSERT(mode); #if B_PERF_BMIPS3300 BDBG_MSG(("perf_init %#x %#x %#x",mode->config[0],mode->config[1],mode->config[2])); bcm_write_perf(6, mode->config[0]); bcm_write_perf(4, mode->config[1]); bcm_write_perf(5, mode->config[2]); bcm_write_perf(0, 0) /* PerfCount0 reset to 0 (it is a decrementing count) */ bcm_write_perf(1, 0) /* PerfCount1 reset to 0 (it is a decrementing count) */ bcm_write_perf(2, 0) /* PerfCount2 reset to 0 (it is a decrementing count) */ bcm_write_perf(3, 0) /* PerfCount3 reset to 0 (it is a decrementing count) */ #elif B_PERF_MIPSR5K BDBG_MSG(("perf_init %#x %#x",mode->config[0],mode->config[1])); bcm_write_perf(0, mode->config[0]); bcm_write_perf(2, mode->config[1]); bcm_write_perf(1, 0) /* PerfCount0 reset to 0 */ bcm_write_perf(3, 0) /* PerfCount1 reset to 0 */ #endif b_perf_mode = mode; return 0; } void bperf_print(const bperf_counter_mode *mode, const bperf_sample *stop, const bperf_sample *start) { unsigned i; if (mode==NULL) { mode = b_perf_mode; } BDBG_ASSERT(mode); for(i=0;idata[i], start->data[i]); BKNI_Printf("%c%s(%u) ", ' ', mode->counter_names[i], diff); } BKNI_Printf("\n"); return; } const bperf_counter_mode * bperf_get_mode(void) { return b_perf_mode; }