blob: ecf4f10d686618c8f5e50e3c192e59da9cdddf16 [file] [log] [blame]
The Android Open Source Project10e23ee2009-03-03 19:30:30 -08001/*
2 * Copyright 2008, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17/*
18 * Binary implementation of the original opcontrol script due to missing tools
19 * like awk, test, etc.
20 */
21
22#include <unistd.h>
23#include <getopt.h>
24#include <stdio.h>
25#include <stdlib.h>
Jean-Baptiste Querud850f372010-05-03 15:16:06 -070026#include <string.h>
The Android Open Source Project10e23ee2009-03-03 19:30:30 -080027#include <errno.h>
28#include <fcntl.h>
29#include <signal.h>
30#include <sys/stat.h>
31
32#include "op_config.h"
33
Bruce Beare751a4432010-03-04 10:30:51 -080034#define verbose(fmt...) if (verbose_print) printf(fmt)
The Android Open Source Project10e23ee2009-03-03 19:30:30 -080035
36/* Experiments found that using a small interval may hang the device, and the
37 * more events tracked simultaneously, the longer the interval has to be.
38 */
Ben Cheng5a4eb4e2009-09-14 16:00:41 -070039
Bruce Beare751a4432010-03-04 10:30:51 -080040#if defined(__i386__) || defined(__x86_64__)
41#define MAX_EVENTS 2
42int min_count[MAX_EVENTS] = {60000, 100000};
43#elif !defined(WITH_ARM_V7_A)
Ben Cheng5a4eb4e2009-09-14 16:00:41 -070044#define MAX_EVENTS 3
Ben Cheng14345072009-09-16 11:31:39 -070045int min_count[MAX_EVENTS] = {150000, 200000, 250000};
Ben Cheng5a4eb4e2009-09-14 16:00:41 -070046#else
Ben Cheng14345072009-09-16 11:31:39 -070047#define MAX_EVENTS 5
Ben Chengafec5b92010-02-22 15:33:08 -080048int min_count[MAX_EVENTS] = {150000, 20000, 25000, 30000, 35000};
Ben Cheng5a4eb4e2009-09-14 16:00:41 -070049#endif
50
Bruce Beare751a4432010-03-04 10:30:51 -080051int verbose_print;
The Android Open Source Project10e23ee2009-03-03 19:30:30 -080052int list_events;
53int show_usage;
54int setup;
55int quick;
56int num_events;
57int start;
58int stop;
59int reset;
60
Ben Cheng5a4eb4e2009-09-14 16:00:41 -070061int selected_events[MAX_EVENTS];
62int selected_counts[MAX_EVENTS];
The Android Open Source Project10e23ee2009-03-03 19:30:30 -080063
Bruce Beare751a4432010-03-04 10:30:51 -080064char callgraph[8];
The Android Open Source Project10e23ee2009-03-03 19:30:30 -080065char kernel_range[512];
66char vmlinux[512];
67
68struct option long_options[] = {
69 {"help", 0, &show_usage, 1},
70 {"list-events", 0, &list_events, 1},
71 {"reset", 0, &reset, 1},
72 {"setup", 0, &setup, 1},
73 {"quick", 0, &quick, 1},
Bruce Beare751a4432010-03-04 10:30:51 -080074 {"callgraph", 1, 0, 'c'},
The Android Open Source Project10e23ee2009-03-03 19:30:30 -080075 {"event", 1, 0, 'e'},
76 {"vmlinux", 1, 0, 'v'},
77 {"kernel-range", 1, 0, 'r'},
78 {"start", 0, &start, 1},
79 {"stop", 0, &stop, 1},
Bruce Beare751a4432010-03-04 10:30:51 -080080 {"dump", 0, 0, 'd'},
The Android Open Source Project10e23ee2009-03-03 19:30:30 -080081 {"shutdown", 0, 0, 'h'},
82 {"status", 0, 0, 't'},
Bruce Beare751a4432010-03-04 10:30:51 -080083 {"verbose", 0, 0, 'V'},
The Android Open Source Project10e23ee2009-03-03 19:30:30 -080084 {0, 0, 0, 0},
85};
86
87struct event_info {
88 int id;
Bruce Beare751a4432010-03-04 10:30:51 -080089 int um;
The Android Open Source Project10e23ee2009-03-03 19:30:30 -080090 const char *name;
91 const char *explanation;
92} event_info[] = {
Bruce Beare751a4432010-03-04 10:30:51 -080093#if defined(__i386__) || defined(__x86_64__)
94 /* INTEL_ARCH_PERFMON events */
95
96 /* 0x3c counters:cpuid um:zero minimum:6000 filter:0 name:CPU_CLK_UNHALTED :
97 * Clock cycles when not halted
98 */
99 {0x3c, 0, "CPU_CLK_UNHALTED",
100 "Clock cycles when not halted" },
101
102 /* event:0x3c counters:cpuid um:one minimum:6000 filter:2 name:UNHALTED_REFERENCE_CYCLES :
103 * Unhalted reference cycles
104 */
105 {0x3c, 1, "UNHALTED_REFERENCE_CYCLES",
106 "Unhalted reference cycles" },
107
108 /* event:0xc0 counters:cpuid um:zero minimum:6000 filter:1 name:INST_RETIRED :
109 * number of instructions retired
110 */
111 {0xc0, 0, "INST_RETIRED",
112 "number of instructions retired"},
113
114 /* event:0x2e counters:cpuid um:x41 minimum:6000 filter:5 name:LLC_MISSES :
115 * Last level cache demand requests from this core that missed the LLC
116 */
117 {0x2e, 0x41, "LLC_MISSES",
118 "Last level cache demand requests from this core that missed the LLC"},
119
120 /* event:0x2e counters:cpuid um:x4f minimum:6000 filter:4 name:LLC_REFS :
121 * Last level cache demand requests from this core
122 */
123 {0x2e, 0x4f, "LLC_REFS",
124 "Last level cache demand requests from this core"},
125
126 /* event:0xc4 counters:cpuid um:zero minimum:500 filter:6 name:BR_INST_RETIRED :
127 * number of branch instructions retired
128 */
129 {0xc4, 0, "BR_INST_RETIRED",
130 "number of branch instructions retired"},
131
132 /* event:0xc5 counters:cpuid um:zero minimum:500 filter:7 name:BR_MISS_PRED_RETIRED :
133 * number of mispredicted branches retired (precise)
134 */
135 {0xc5, 0, "BR_MISS_PRED_RETIRED",
136 "number of mispredicted branches retired (precise)"},
137
138#elif !defined(WITH_ARM_V7_A)
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700139 /* ARM V6 events */
Bruce Beare751a4432010-03-04 10:30:51 -0800140 {0x00, 0, "IFU_IFETCH_MISS",
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800141 "number of instruction fetch misses"},
Bruce Beare751a4432010-03-04 10:30:51 -0800142 {0x01, 0, "CYCLES_IFU_MEM_STALL",
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800143 "cycles instruction fetch pipe is stalled"},
Bruce Beare751a4432010-03-04 10:30:51 -0800144 {0x02, 0, "CYCLES_DATA_STALL",
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800145 "cycles stall occurs for due to data dependency"},
Bruce Beare751a4432010-03-04 10:30:51 -0800146 {0x03, 0, "ITLB_MISS",
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800147 "number of Instruction MicroTLB misses"},
Bruce Beare751a4432010-03-04 10:30:51 -0800148 {0x04, 0, "DTLB_MISS",
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800149 "number of Data MicroTLB misses"},
Bruce Beare751a4432010-03-04 10:30:51 -0800150 {0x05, 0, "BR_INST_EXECUTED",
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800151 "branch instruction executed w/ or w/o program flow change"},
Bruce Beare751a4432010-03-04 10:30:51 -0800152 {0x06, 0, "BR_INST_MISS_PRED",
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800153 "branch mispredicted"},
Bruce Beare751a4432010-03-04 10:30:51 -0800154 {0x07, 0, "INSN_EXECUTED",
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800155 "instructions executed"},
Bruce Beare751a4432010-03-04 10:30:51 -0800156 {0x09, 0, "DCACHE_ACCESS",
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800157 "data cache access, cacheable locations"},
Bruce Beare751a4432010-03-04 10:30:51 -0800158 {0x0a, 0, "DCACHE_ACCESS_ALL",
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800159 "data cache access, all locations"},
Bruce Beare751a4432010-03-04 10:30:51 -0800160 {0x0b, 0, "DCACHE_MISS",
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800161 "data cache miss"},
Bruce Beare751a4432010-03-04 10:30:51 -0800162 {0x0c, 0, "DCACHE_WB",
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800163 "data cache writeback, 1 event for every half cacheline"},
Bruce Beare751a4432010-03-04 10:30:51 -0800164 {0x0d, 0, "PC_CHANGE",
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800165 "number of times the program counter was changed without a mode switch"},
Bruce Beare751a4432010-03-04 10:30:51 -0800166 {0x0f, 0, "TLB_MISS",
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800167 "Main TLB miss"},
Bruce Beare751a4432010-03-04 10:30:51 -0800168 {0x10, 0, "EXP_EXTERNAL",
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800169 "Explicit external data access"},
Bruce Beare751a4432010-03-04 10:30:51 -0800170 {0x11, 0, "LSU_STALL",
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800171 "cycles stalled because Load Store request queue is full"},
Bruce Beare751a4432010-03-04 10:30:51 -0800172 {0x12, 0, "WRITE_DRAIN",
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800173 "Times write buffer was drained"},
Bruce Beare751a4432010-03-04 10:30:51 -0800174 {0xff, 0, "CPU_CYCLES",
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800175 "clock cycles counter"},
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700176#else
177 /* ARM V7 events */
Bruce Beare751a4432010-03-04 10:30:51 -0800178 {0x00, 0, "PMNC_SW_INCR",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700179 "Software increment of PMNC registers"},
Bruce Beare751a4432010-03-04 10:30:51 -0800180 {0x01, 0, "IFETCH_MISS",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700181 "Instruction fetch misses from cache or normal cacheable memory"},
Bruce Beare751a4432010-03-04 10:30:51 -0800182 {0x02, 0, "ITLB_MISS",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700183 "Instruction fetch misses from TLB"},
Bruce Beare751a4432010-03-04 10:30:51 -0800184 {0x03, 0, "DCACHE_REFILL",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700185 "Data R/W operation that causes a refill from cache or normal cacheable"
186 "memory"},
Bruce Beare751a4432010-03-04 10:30:51 -0800187 {0x04, 0, "DCACHE_ACCESS",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700188 "Data R/W from cache"},
Bruce Beare751a4432010-03-04 10:30:51 -0800189 {0x05, 0, "DTLB_REFILL",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700190 "Data R/W that causes a TLB refill"},
Bruce Beare751a4432010-03-04 10:30:51 -0800191 {0x06, 0, "DREAD",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700192 "Data read architecturally executed (note: architecturally executed = for"
193 "instructions that are unconditional or that pass the condition code)"},
Bruce Beare751a4432010-03-04 10:30:51 -0800194 {0x07, 0, "DWRITE",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700195 "Data write architecturally executed"},
Bruce Beare751a4432010-03-04 10:30:51 -0800196 {0x08, 0, "INSTR_EXECUTED",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700197 "All executed instructions"},
Bruce Beare751a4432010-03-04 10:30:51 -0800198 {0x09, 0, "EXC_TAKEN",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700199 "Exception taken"},
Bruce Beare751a4432010-03-04 10:30:51 -0800200 {0x0A, 0, "EXC_EXECUTED",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700201 "Exception return architecturally executed"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400202 {0x0B, 0, "CID_WRITE",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700203 "Instruction that writes to the Context ID Register architecturally"
204 "executed"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400205 {0x0C, 0, "PC_WRITE",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700206 "SW change of PC, architecturally executed (not by exceptions)"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400207 {0x0D, 0, "PC_IMM_BRANCH",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700208 "Immediate branch instruction executed (taken or not)"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400209 {0x0E, 0, "PC_PROC_RETURN",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700210 "Procedure return architecturally executed (not by exceptions)"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400211 {0x0F, 0, "UNALIGNED_ACCESS",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700212 "Unaligned access architecturally executed"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400213 {0x10, 0, "PC_BRANCH_MIS_PRED",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700214 "Branch mispredicted or not predicted. Counts pipeline flushes because of"
215 "misprediction"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400216 {0x12, 0, "PC_BRANCH_MIS_USED",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700217 "Branch or change in program flow that could have been predicted"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400218 {0x40, 0, "WRITE_BUFFER_FULL",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700219 "Any write buffer full cycle"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400220 {0x41, 0, "L2_STORE_MERGED",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700221 "Any store that is merged in L2 cache"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400222 {0x42, 0, "L2_STORE_BUFF",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700223 "Any bufferable store from load/store to L2 cache"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400224 {0x43, 0, "L2_ACCESS",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700225 "Any access to L2 cache"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400226 {0x44, 0, "L2_CACH_MISS",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700227 "Any cacheable miss in L2 cache"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400228 {0x45, 0, "AXI_READ_CYCLES",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700229 "Number of cycles for an active AXI read"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400230 {0x46, 0, "AXI_WRITE_CYCLES",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700231 "Number of cycles for an active AXI write"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400232 {0x47, 0, "MEMORY_REPLAY",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700233 "Any replay event in the memory subsystem"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400234 {0x48, 0, "UNALIGNED_ACCESS_REPLAY",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700235 "Unaligned access that causes a replay"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400236 {0x49, 0, "L1_DATA_MISS",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700237 "L1 data cache miss as a result of the hashing algorithm"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400238 {0x4A, 0, "L1_INST_MISS",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700239 "L1 instruction cache miss as a result of the hashing algorithm"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400240 {0x4B, 0, "L1_DATA_COLORING",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700241 "L1 data access in which a page coloring alias occurs"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400242 {0x4C, 0, "L1_NEON_DATA",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700243 "NEON data access that hits L1 cache"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400244 {0x4D, 0, "L1_NEON_CACH_DATA",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700245 "NEON cacheable data access that hits L1 cache"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400246 {0x4E, 0, "L2_NEON",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700247 "L2 access as a result of NEON memory access"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400248 {0x4F, 0, "L2_NEON_HIT",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700249 "Any NEON hit in L2 cache"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400250 {0x50, 0, "L1_INST",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700251 "Any L1 instruction cache access, excluding CP15 cache accesses"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400252 {0x51, 0, "PC_RETURN_MIS_PRED",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700253 "Return stack misprediction at return stack pop"
254 "(incorrect target address)"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400255 {0x52, 0, "PC_BRANCH_FAILED",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700256 "Branch prediction misprediction"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400257 {0x53, 0, "PC_BRANCH_TAKEN",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700258 "Any predicted branch that is taken"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400259 {0x54, 0, "PC_BRANCH_EXECUTED",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700260 "Any taken branch that is executed"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400261 {0x55, 0, "OP_EXECUTED",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700262 "Number of operations executed"
263 "(in instruction or mutli-cycle instruction)"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400264 {0x56, 0, "CYCLES_INST_STALL",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700265 "Cycles where no instruction available"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400266 {0x57, 0, "CYCLES_INST",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700267 "Number of instructions issued in a cycle"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400268 {0x58, 0, "CYCLES_NEON_DATA_STALL",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700269 "Number of cycles the processor waits on MRC data from NEON"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400270 {0x59, 0, "CYCLES_NEON_INST_STALL",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700271 "Number of cycles the processor waits on NEON instruction queue or"
272 "NEON load queue"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400273 {0x5A, 0, "NEON_CYCLES",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700274 "Number of cycles NEON and integer processors are not idle"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400275 {0x70, 0, "PMU0_EVENTS",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700276 "Number of events from external input source PMUEXTIN[0]"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400277 {0x71, 0, "PMU1_EVENTS",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700278 "Number of events from external input source PMUEXTIN[1]"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400279 {0x72, 0, "PMU_EVENTS",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700280 "Number of events from both external input sources PMUEXTIN[0]"
281 "and PMUEXTIN[1]"},
Mike Lockwoode815c522010-04-30 08:30:05 -0400282 {0xFF, 0, "CPU_CYCLES",
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700283 "Number of CPU cycles"},
284#endif
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800285};
286
Ben Cheng14345072009-09-16 11:31:39 -0700287void usage()
288{
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800289 printf("\nopcontrol: usage:\n"
290 " --list-events list event types\n"
291 " --help this message\n"
Bruce Beare751a4432010-03-04 10:30:51 -0800292 " --verbose show extra status\n"
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800293 " --setup setup directories\n"
Bruce Beare751a4432010-03-04 10:30:51 -0800294#if defined(__i386__) || defined(__x86_64__)
295 " --quick setup and select CPU_CLK_UNHALTED:60000\n"
296#else
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800297 " --quick setup and select CPU_CYCLES:150000\n"
Bruce Beare751a4432010-03-04 10:30:51 -0800298#endif
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800299 " --status show configuration\n"
300 " --start start data collection\n"
301 " --stop stop data collection\n"
302 " --reset clears out data from current session\n"
303 " --shutdown kill the oprofile daeman\n"
Bruce Beare751a4432010-03-04 10:30:51 -0800304 " --callgraph=depth callgraph depth\n"
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800305 " --event=eventspec\n"
306 " Choose an event. May be specified multiple times.\n"
307 " eventspec is in the form of name[:count], where :\n"
308 " name: event name, see \"opcontrol --list-events\"\n"
309 " count: reset counter value\n"
310 " --vmlinux=file vmlinux kernel image\n"
311 " --kernel-range=start,end\n"
312 " kernel range vma address in hexadecimal\n"
313 );
314}
315
Ben Cheng14345072009-09-16 11:31:39 -0700316void setup_session_dir()
317{
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800318 int fd;
319
320 fd = open(OP_DATA_DIR, O_RDONLY);
321 if (fd != -1) {
322 system("rm -r "OP_DATA_DIR);
323 close(fd);
324 }
325
Mike Playled0950102010-07-09 17:02:22 +0100326 if (mkdir(OP_DATA_DIR, 0755)) {
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800327 fprintf(stderr, "Cannot create directory \"%s\": %s\n",
328 OP_DATA_DIR, strerror(errno));
329 }
Mike Playled0950102010-07-09 17:02:22 +0100330 if (mkdir(OP_DATA_DIR"/samples", 0755)) {
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800331 fprintf(stderr, "Cannot create directory \"%s\": %s\n",
332 OP_DATA_DIR"/samples", strerror(errno));
333 }
334}
335
Ben Cheng14345072009-09-16 11:31:39 -0700336int do_setup()
337{
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800338 char dir[1024];
339
340 setup_session_dir();
341
Mike Playled0950102010-07-09 17:02:22 +0100342 if (mkdir(OP_DRIVER_BASE, 0755)) {
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800343 fprintf(stderr, "Cannot create directory "OP_DRIVER_BASE": %s\n",
344 strerror(errno));
345 return -1;
346 }
347 if (system("mount -t oprofilefs nodev "OP_DRIVER_BASE)) {
348 return -1;
349 }
350 return 0;
351}
352
353void do_list_events()
354{
355 unsigned int i;
356
357 printf("%-20s: %s\n", "name", "meaning");
358 printf("----------------------------------------"
359 "--------------------------------------\n");
360 for (i = 0; i < sizeof(event_info)/sizeof(struct event_info); i++) {
361 printf("%-20s: %s\n", event_info[i].name, event_info[i].explanation);
362 }
363}
364
Ben Cheng14345072009-09-16 11:31:39 -0700365int find_event_idx_from_name(const char *name)
366{
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800367 unsigned int i;
368
369 for (i = 0; i < sizeof(event_info)/sizeof(struct event_info); i++) {
370 if (!strcmp(name, event_info[i].name)) {
371 return i;
372 }
373 }
374 return -1;
375}
376
Ben Cheng14345072009-09-16 11:31:39 -0700377const char * find_event_name_from_id(int id)
378{
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800379 unsigned int i;
380
381 for (i = 0; i < sizeof(event_info)/sizeof(struct event_info); i++) {
382 if (event_info[i].id == id) {
383 return event_info[i].name;
384 }
385 }
386 return NULL;
387}
388
Ben Cheng14345072009-09-16 11:31:39 -0700389int process_event(const char *event_spec)
390{
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800391 char event_name[512];
392 char count_name[512];
393 unsigned int i;
Ben Cheng14345072009-09-16 11:31:39 -0700394 int event_idx;
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800395 int count_val;
396
397 strncpy(event_name, event_spec, 512);
398 count_name[0] = 0;
399
400 /* First, check if the name is followed by ":" */
401 for (i = 0; i < strlen(event_name); i++) {
402 if (event_name[i] == 0) {
403 break;
404 }
405 if (event_name[i] == ':') {
406 strncpy(count_name, event_name+i+1, 512);
407 event_name[i] = 0;
408 break;
409 }
410 }
Ben Cheng14345072009-09-16 11:31:39 -0700411 event_idx = find_event_idx_from_name(event_name);
412 if (event_idx == -1) {
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800413 fprintf(stderr, "Unknown event name: %s\n", event_name);
414 return -1;
415 }
416
417 /* Use defualt count */
418 if (count_name[0] == 0) {
419 count_val = min_count[0];
420 } else {
421 count_val = atoi(count_name);
422 }
423
Ben Cheng14345072009-09-16 11:31:39 -0700424 selected_events[num_events] = event_idx;
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800425 selected_counts[num_events++] = count_val;
Ben Cheng14345072009-09-16 11:31:39 -0700426 verbose("event_id is %d\n", event_info[event_idx].id);
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800427 verbose("count_val is %d\n", count_val);
428 return 0;
429}
430
431int echo_dev(const char* str, int val, const char* file, int counter)
432{
433 char fullname[512];
434 char content[128];
435 int fd;
436
437 if (counter >= 0) {
438 snprintf(fullname, 512, OP_DRIVER_BASE"/%d/%s", counter, file);
439 }
440 else {
441 snprintf(fullname, 512, OP_DRIVER_BASE"/%s", file);
442 }
443 fd = open(fullname, O_WRONLY);
444 if (fd<0) {
445 fprintf(stderr, "Cannot open %s: %s\n", fullname, strerror(errno));
446 return fd;
447 }
448 if (str == 0) {
449 sprintf(content, "%d", val);
450 }
451 else {
452 strncpy(content, str, 128);
453 }
454 verbose("Configure %s (%s)\n", fullname, content);
455 write(fd, content, strlen(content));
456 close(fd);
457 return 0;
458}
459
460int read_num(const char* file)
461{
462 char buffer[256];
463 int fd = open(file, O_RDONLY);
464 if (fd<0) return -1;
465 int rd = read(fd, buffer, sizeof(buffer)-1);
466 buffer[rd] = 0;
467 return atoi(buffer);
468}
469
470void do_status()
471{
472 int num;
473 char fullname[512];
474 int i;
475
476 printf("Driver directory: %s\n", OP_DRIVER_BASE);
477 printf("Session directory: %s\n", OP_DATA_DIR);
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700478 for (i = 0; i < MAX_EVENTS; i++) {
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800479 sprintf(fullname, OP_DRIVER_BASE"/%d/enabled", i);
480 num = read_num(fullname);
481 if (num > 0) {
482 printf("Counter %d:\n", i);
483
484 /* event name */
485 sprintf(fullname, OP_DRIVER_BASE"/%d/event", i);
486 num = read_num(fullname);
487 printf(" name: %s\n", find_event_name_from_id(num));
488
489 /* profile interval */
490 sprintf(fullname, OP_DRIVER_BASE"/%d/count", i);
491 num = read_num(fullname);
492 printf(" count: %d\n", num);
493 }
494 else {
495 printf("Counter %d disabled\n", i);
496 }
497 }
498
499 num = read_num(OP_DATA_DIR"/lock");
500 if (num >= 0) {
501 int fd;
502 /* Still needs to check if this lock is left-over */
503 sprintf(fullname, "/proc/%d", num);
504 fd = open(fullname, O_RDONLY);
505 if (fd == -1) {
506 printf("Session directory is not clean - do \"opcontrol --setup\""
507 " before you continue\n");
508 return;
509 }
510 else {
511 close(fd);
512 printf("oprofiled pid: %d\n", num);
513 num = read_num(OP_DRIVER_BASE"/enable");
514 printf("profiler is%s running\n", num == 0 ? " not" : "");
515 num = read_num(OP_DRIVER_BASE"/stats/cpu0/sample_received");
516 printf(" %9u samples received\n", num);
517 num = read_num(OP_DRIVER_BASE"/stats/cpu0/sample_lost_overflow");
518 printf(" %9u samples lost overflow\n", num);
Bruce Beare751a4432010-03-04 10:30:51 -0800519
520#if defined(__i386__) || defined(__x86_64__)
521 /* FIXME on ARM - backtrace seems broken there */
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800522 num = read_num(OP_DRIVER_BASE"/stats/cpu0/backtrace_aborted");
523 printf(" %9u backtrace aborted\n", num);
524 num = read_num(OP_DRIVER_BASE"/backtrace_depth");
525 printf(" %9u backtrace_depth\n", num);
526#endif
527 }
528 }
529 else {
530 printf("oprofiled is not running\n");
531 }
532}
533
534void do_reset()
535{
536 int fd;
537
538 fd = open(OP_DATA_DIR"/samples/current", O_RDONLY);
539 if (fd == -1) {
540 return;
541 }
542 close(fd);
543 system("rm -r "OP_DATA_DIR"/samples/current");
544}
545
546int main(int argc, char * const argv[])
547{
548 int option_index;
549 char command[1024];
550
551 /* Initialize default strings */
552 strcpy(vmlinux, "--no-vmlinux");
553 strcpy(kernel_range, "");
554
555 while (1) {
Bruce Beare751a4432010-03-04 10:30:51 -0800556 int c = getopt_long(argc, argv, "c:e:v:r:dhVt", long_options, &option_index);
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800557 if (c == -1) {
558 break;
559 }
560 switch (c) {
561 case 0:
562 break;
Bruce Beare751a4432010-03-04 10:30:51 -0800563 /* --callgraph */
564 case 'c':
565 strncpy(callgraph, optarg, sizeof(callgraph));
566 break;
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800567 /* --event */
568 case 'e':
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700569 if (num_events == MAX_EVENTS) {
570 fprintf(stderr, "More than %d events specified\n",
571 MAX_EVENTS);
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800572 exit(1);
573 }
574 if (process_event(optarg)) {
575 exit(1);
576 }
577 break;
578 /* --vmlinux */
579 case 'v':
580 sprintf(vmlinux, "-k %s", optarg);
581 break;
582 /* --kernel-range */
583 case 'r':
584 sprintf(kernel_range, "-r %s", optarg);
585 break;
Bruce Beare751a4432010-03-04 10:30:51 -0800586 case 'd':
587 /* --dump */ {
588 int pid = read_num(OP_DATA_DIR"/lock");
589 echo_dev("1", 0, "dump", -1);
590 if (pid >= 0) {
591 sleep(1);
592 kill(pid, SIGHUP);
593 }
594 break;
595 }
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800596 /* --shutdown */
597 case 'h': {
598 int pid = read_num(OP_DATA_DIR"/lock");
599 if (pid >= 0) {
Bruce Beare751a4432010-03-04 10:30:51 -0800600 kill(pid, SIGHUP); /* Politely ask the daemon to close files */
601 sleep(1);
602 kill(pid, SIGTERM);/* Politely ask the daemon to die */
603 sleep(1);
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800604 kill(pid, SIGKILL);
605 }
606 setup_session_dir();
607 break;
608 }
Bruce Beare751a4432010-03-04 10:30:51 -0800609 /* --verbose */
610 case 'V':
611 verbose_print++;
612 break;
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800613 /* --status */
614 case 't':
615 do_status();
616 break;
617 default:
618 usage();
619 exit(1);
620 }
621 }
622 verbose("list_events = %d\n", list_events);
623 verbose("setup = %d\n", setup);
624
625 if (list_events) {
626 do_list_events();
627 }
628
629 if (quick) {
Bruce Beare751a4432010-03-04 10:30:51 -0800630#if defined(__i386__) || defined(__x86_64__)
631 process_event("CPU_CLK_UNHALTED");
632#else
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800633 process_event("CPU_CYCLES");
Bruce Beare751a4432010-03-04 10:30:51 -0800634#endif
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800635 setup = 1;
636 }
637
638 if (reset) {
639 do_reset();
640 }
641
642 if (show_usage) {
643 usage();
644 }
645
646 if (setup) {
647 if (do_setup()) {
648 fprintf(stderr, "do_setup failed");
649 exit(1);
650 }
651 }
652
Bruce Beare751a4432010-03-04 10:30:51 -0800653 if (strlen(callgraph)) {
654 echo_dev(callgraph, 0, "backtrace_depth", -1);
655 }
656
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800657 if (num_events != 0) {
658 int i;
659
660 strcpy(command, "oprofiled --session-dir="OP_DATA_DIR);
661
Bruce Beare751a4432010-03-04 10:30:51 -0800662#if defined(__i386__) || defined(__x86_64__)
663 /* Nothing */
664#elif !defined(WITH_ARM_V7_A)
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800665 /* Since counter #3 can only handle CPU_CYCLES, check and shuffle the
666 * order a bit so that the maximal number of events can be profiled
667 * simultaneously
668 */
669 if (num_events == 3) {
670 for (i = 0; i < num_events; i++) {
671 int event_idx = selected_events[i];
672
673 if (event_info[event_idx].id == 0xff) {
674 break;
675 }
676 }
677
678 /* No CPU_CYCLES is found */
679 if (i == 3) {
680 fprintf(stderr, "You can only specify three events if one of "
681 "them is CPU_CYCLES\n");
682 exit(1);
683 }
684 /* Swap CPU_CYCLES to counter #2 (starting from #0)*/
685 else if (i != 2) {
686 int temp;
687
688 temp = selected_events[2];
689 selected_events[2] = selected_events[i];
690 selected_events[i] = temp;
691
692 temp = selected_counts[2];
693 selected_counts[2] = selected_counts[i];
694 selected_counts[i] = temp;
695 }
696 }
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700697#endif
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800698
699
700 /* Configure the counters and enable them */
701 for (i = 0; i < num_events; i++) {
702 int event_idx = selected_events[i];
703 int setup_result = 0;
704
705 if (i == 0) {
706 snprintf(command+strlen(command), 1024 - strlen(command),
707 " --events=");
708 }
709 else {
710 snprintf(command+strlen(command), 1024 - strlen(command),
711 ",");
712 }
713 /* Compose name:id:count:unit_mask:kernel:user, something like
714 * --events=CYCLES_DATA_STALL:2:0:200000:0:1:1,....
715 */
716 snprintf(command+strlen(command), 1024 - strlen(command),
Bruce Beare751a4432010-03-04 10:30:51 -0800717 "%s:%d:%d:%d:%d:1:1",
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800718 event_info[event_idx].name,
719 event_info[event_idx].id,
720 i,
Bruce Beare751a4432010-03-04 10:30:51 -0800721 selected_counts[i],
722 event_info[event_idx].um);
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800723
724 setup_result |= echo_dev("1", 0, "user", i);
725 setup_result |= echo_dev("1", 0, "kernel", i);
Bruce Beare751a4432010-03-04 10:30:51 -0800726 setup_result |= echo_dev(NULL, event_info[event_idx].um, "unit_mask", i);
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800727 setup_result |= echo_dev("1", 0, "enabled", i);
728 setup_result |= echo_dev(NULL, selected_counts[i], "count", i);
729 setup_result |= echo_dev(NULL, event_info[event_idx].id,
730 "event", i);
731 if (setup_result) {
732 fprintf(stderr, "Counter configuration failed for %s\n",
733 event_info[event_idx].name);
734 fprintf(stderr, "Did you do \"opcontrol --setup\" first?\n");
735 exit(1);
736 }
737 }
738
739 /* Disable the unused counters */
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700740 for (i = num_events; i < MAX_EVENTS; i++) {
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800741 echo_dev("0", 0, "enabled", i);
742 }
743
744 snprintf(command+strlen(command), 1024 - strlen(command), " %s",
745 vmlinux);
746 if (kernel_range[0]) {
747 snprintf(command+strlen(command), 1024 - strlen(command), " %s",
748 kernel_range);
749 }
750 verbose("command: %s\n", command);
751 system(command);
752 }
753
754 if (start) {
755 echo_dev("1", 0, "enable", -1);
756 }
757
758 if (stop) {
Ben Chengafec5b92010-02-22 15:33:08 -0800759 echo_dev("1", 0, "dump", -1);
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800760 echo_dev("0", 0, "enable", -1);
761 }
762}