1*288bf522SAndroid Build Coastguard Worker /*
2*288bf522SAndroid Build Coastguard Worker * Copyright (C) 2016 The Android Open Source Project
3*288bf522SAndroid Build Coastguard Worker *
4*288bf522SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*288bf522SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*288bf522SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*288bf522SAndroid Build Coastguard Worker *
8*288bf522SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*288bf522SAndroid Build Coastguard Worker *
10*288bf522SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*288bf522SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*288bf522SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*288bf522SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*288bf522SAndroid Build Coastguard Worker * limitations under the License.
15*288bf522SAndroid Build Coastguard Worker */
16*288bf522SAndroid Build Coastguard Worker
17*288bf522SAndroid Build Coastguard Worker #include "Profiler.h"
18*288bf522SAndroid Build Coastguard Worker
19*288bf522SAndroid Build Coastguard Worker #include <stdlib.h>
20*288bf522SAndroid Build Coastguard Worker #include <string.h>
21*288bf522SAndroid Build Coastguard Worker #include <unistd.h>
22*288bf522SAndroid Build Coastguard Worker
23*288bf522SAndroid Build Coastguard Worker #include <algorithm>
24*288bf522SAndroid Build Coastguard Worker #include <iostream>
25*288bf522SAndroid Build Coastguard Worker
26*288bf522SAndroid Build Coastguard Worker #if defined(__linux__)
27*288bf522SAndroid Build Coastguard Worker
28*288bf522SAndroid Build Coastguard Worker #include <sys/syscall.h>
29*288bf522SAndroid Build Coastguard Worker
30*288bf522SAndroid Build Coastguard Worker #ifdef __ARM_ARCH
31*288bf522SAndroid Build Coastguard Worker enum ARMv8PmuPerfTypes{
32*288bf522SAndroid Build Coastguard Worker // Common micro-architecture events
33*288bf522SAndroid Build Coastguard Worker ARMV8_PMUV3_PERFCTR_L1_ICACHE_REFILL = 0x01,
34*288bf522SAndroid Build Coastguard Worker ARMV8_PMUV3_PERFCTR_L1_ICACHE_ACCESS = 0x14,
35*288bf522SAndroid Build Coastguard Worker ARMV8_PMUV3_PERFCTR_L2_CACHE_ACCESS = 0x16,
36*288bf522SAndroid Build Coastguard Worker ARMV8_PMUV3_PERFCTR_L2_CACHE_REFILL = 0x17,
37*288bf522SAndroid Build Coastguard Worker ARMV8_PMUV3_PERFCTR_L2_CACHE_WB = 0x18,
38*288bf522SAndroid Build Coastguard Worker };
39*288bf522SAndroid Build Coastguard Worker #endif
40*288bf522SAndroid Build Coastguard Worker
perf_event_open(struct perf_event_attr * hw_event,pid_t pid,int cpu,int group_fd,unsigned long flags)41*288bf522SAndroid Build Coastguard Worker static int perf_event_open(struct perf_event_attr* hw_event, pid_t pid,
42*288bf522SAndroid Build Coastguard Worker int cpu, int group_fd, unsigned long flags) {
43*288bf522SAndroid Build Coastguard Worker return syscall(__NR_perf_event_open, hw_event, pid, cpu, group_fd, flags);
44*288bf522SAndroid Build Coastguard Worker }
45*288bf522SAndroid Build Coastguard Worker
46*288bf522SAndroid Build Coastguard Worker #endif // __linux__
47*288bf522SAndroid Build Coastguard Worker
48*288bf522SAndroid Build Coastguard Worker namespace utils {
49*288bf522SAndroid Build Coastguard Worker
get()50*288bf522SAndroid Build Coastguard Worker Profiler& Profiler::get() noexcept {
51*288bf522SAndroid Build Coastguard Worker static Profiler sProfiler;
52*288bf522SAndroid Build Coastguard Worker return sProfiler;
53*288bf522SAndroid Build Coastguard Worker }
54*288bf522SAndroid Build Coastguard Worker
Profiler()55*288bf522SAndroid Build Coastguard Worker Profiler::Profiler() noexcept {
56*288bf522SAndroid Build Coastguard Worker std::uninitialized_fill(mCountersFd.begin(), mCountersFd.end(), -1);
57*288bf522SAndroid Build Coastguard Worker Profiler::resetEvents(EV_CPU_CYCLES | EV_L1D_RATES | EV_BPU_RATES);
58*288bf522SAndroid Build Coastguard Worker }
59*288bf522SAndroid Build Coastguard Worker
~Profiler()60*288bf522SAndroid Build Coastguard Worker Profiler::~Profiler() noexcept {
61*288bf522SAndroid Build Coastguard Worker for (int fd : mCountersFd) {
62*288bf522SAndroid Build Coastguard Worker if (fd >= 0) {
63*288bf522SAndroid Build Coastguard Worker close(fd);
64*288bf522SAndroid Build Coastguard Worker }
65*288bf522SAndroid Build Coastguard Worker }
66*288bf522SAndroid Build Coastguard Worker }
67*288bf522SAndroid Build Coastguard Worker
resetEvents(uint32_t eventMask)68*288bf522SAndroid Build Coastguard Worker uint32_t Profiler::resetEvents(uint32_t eventMask) noexcept {
69*288bf522SAndroid Build Coastguard Worker // close all counters
70*288bf522SAndroid Build Coastguard Worker for (int& fd : mCountersFd) {
71*288bf522SAndroid Build Coastguard Worker if (fd >= 0) {
72*288bf522SAndroid Build Coastguard Worker close(fd);
73*288bf522SAndroid Build Coastguard Worker fd = -1;
74*288bf522SAndroid Build Coastguard Worker }
75*288bf522SAndroid Build Coastguard Worker }
76*288bf522SAndroid Build Coastguard Worker mEnabledEvents = 0;
77*288bf522SAndroid Build Coastguard Worker
78*288bf522SAndroid Build Coastguard Worker #if defined(__linux__)
79*288bf522SAndroid Build Coastguard Worker
80*288bf522SAndroid Build Coastguard Worker struct perf_event_attr pe;
81*288bf522SAndroid Build Coastguard Worker memset(&pe, 0, sizeof(struct perf_event_attr));
82*288bf522SAndroid Build Coastguard Worker pe.type = PERF_TYPE_HARDWARE;
83*288bf522SAndroid Build Coastguard Worker pe.size = sizeof(struct perf_event_attr);
84*288bf522SAndroid Build Coastguard Worker pe.config = PERF_COUNT_HW_INSTRUCTIONS;
85*288bf522SAndroid Build Coastguard Worker pe.disabled = 1;
86*288bf522SAndroid Build Coastguard Worker pe.exclude_kernel = 1;
87*288bf522SAndroid Build Coastguard Worker pe.exclude_hv = 1;
88*288bf522SAndroid Build Coastguard Worker pe.read_format = PERF_FORMAT_GROUP |
89*288bf522SAndroid Build Coastguard Worker PERF_FORMAT_ID |
90*288bf522SAndroid Build Coastguard Worker PERF_FORMAT_TOTAL_TIME_ENABLED |
91*288bf522SAndroid Build Coastguard Worker PERF_FORMAT_TOTAL_TIME_RUNNING;
92*288bf522SAndroid Build Coastguard Worker
93*288bf522SAndroid Build Coastguard Worker uint8_t count = 0;
94*288bf522SAndroid Build Coastguard Worker int fd = perf_event_open(&pe, 0, -1, -1, 0);
95*288bf522SAndroid Build Coastguard Worker if (fd >= 0) {
96*288bf522SAndroid Build Coastguard Worker const int groupFd = fd;
97*288bf522SAndroid Build Coastguard Worker mIds[INSTRUCTIONS] = count++;
98*288bf522SAndroid Build Coastguard Worker mCountersFd[INSTRUCTIONS] = fd;
99*288bf522SAndroid Build Coastguard Worker
100*288bf522SAndroid Build Coastguard Worker pe.read_format = PERF_FORMAT_GROUP | PERF_FORMAT_ID;
101*288bf522SAndroid Build Coastguard Worker
102*288bf522SAndroid Build Coastguard Worker if (eventMask & EV_CPU_CYCLES) {
103*288bf522SAndroid Build Coastguard Worker pe.type = PERF_TYPE_HARDWARE;
104*288bf522SAndroid Build Coastguard Worker pe.config = PERF_COUNT_HW_CPU_CYCLES;
105*288bf522SAndroid Build Coastguard Worker mCountersFd[CPU_CYCLES] = perf_event_open(&pe, 0, -1, groupFd, 0);
106*288bf522SAndroid Build Coastguard Worker if (mCountersFd[CPU_CYCLES] > 0) {
107*288bf522SAndroid Build Coastguard Worker mIds[CPU_CYCLES] = count++;
108*288bf522SAndroid Build Coastguard Worker mEnabledEvents |= EV_CPU_CYCLES;
109*288bf522SAndroid Build Coastguard Worker }
110*288bf522SAndroid Build Coastguard Worker }
111*288bf522SAndroid Build Coastguard Worker
112*288bf522SAndroid Build Coastguard Worker if (eventMask & EV_L1D_REFS) {
113*288bf522SAndroid Build Coastguard Worker pe.type = PERF_TYPE_HARDWARE;
114*288bf522SAndroid Build Coastguard Worker pe.config = PERF_COUNT_HW_CACHE_REFERENCES;
115*288bf522SAndroid Build Coastguard Worker mCountersFd[DCACHE_REFS] = perf_event_open(&pe, 0, -1, groupFd, 0);
116*288bf522SAndroid Build Coastguard Worker if (mCountersFd[DCACHE_REFS] > 0) {
117*288bf522SAndroid Build Coastguard Worker mIds[DCACHE_REFS] = count++;
118*288bf522SAndroid Build Coastguard Worker mEnabledEvents |= EV_L1D_REFS;
119*288bf522SAndroid Build Coastguard Worker }
120*288bf522SAndroid Build Coastguard Worker }
121*288bf522SAndroid Build Coastguard Worker
122*288bf522SAndroid Build Coastguard Worker if (eventMask & EV_L1D_MISSES) {
123*288bf522SAndroid Build Coastguard Worker pe.type = PERF_TYPE_HARDWARE;
124*288bf522SAndroid Build Coastguard Worker pe.config = PERF_COUNT_HW_CACHE_MISSES;
125*288bf522SAndroid Build Coastguard Worker mCountersFd[DCACHE_MISSES] = perf_event_open(&pe, 0, -1, groupFd, 0);
126*288bf522SAndroid Build Coastguard Worker if (mCountersFd[DCACHE_MISSES] > 0) {
127*288bf522SAndroid Build Coastguard Worker mIds[DCACHE_MISSES] = count++;
128*288bf522SAndroid Build Coastguard Worker mEnabledEvents |= EV_L1D_MISSES;
129*288bf522SAndroid Build Coastguard Worker }
130*288bf522SAndroid Build Coastguard Worker }
131*288bf522SAndroid Build Coastguard Worker
132*288bf522SAndroid Build Coastguard Worker if (eventMask & EV_BPU_REFS) {
133*288bf522SAndroid Build Coastguard Worker pe.type = PERF_TYPE_HARDWARE;
134*288bf522SAndroid Build Coastguard Worker pe.config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS;
135*288bf522SAndroid Build Coastguard Worker mCountersFd[BRANCHES] = perf_event_open(&pe, 0, -1, groupFd, 0);
136*288bf522SAndroid Build Coastguard Worker if (mCountersFd[BRANCHES] > 0) {
137*288bf522SAndroid Build Coastguard Worker mIds[BRANCHES] = count++;
138*288bf522SAndroid Build Coastguard Worker mEnabledEvents |= EV_BPU_REFS;
139*288bf522SAndroid Build Coastguard Worker }
140*288bf522SAndroid Build Coastguard Worker }
141*288bf522SAndroid Build Coastguard Worker
142*288bf522SAndroid Build Coastguard Worker if (eventMask & EV_BPU_MISSES) {
143*288bf522SAndroid Build Coastguard Worker pe.type = PERF_TYPE_HARDWARE;
144*288bf522SAndroid Build Coastguard Worker pe.config = PERF_COUNT_HW_BRANCH_MISSES;
145*288bf522SAndroid Build Coastguard Worker mCountersFd[BRANCH_MISSES] = perf_event_open(&pe, 0, -1, groupFd, 0);
146*288bf522SAndroid Build Coastguard Worker if (mCountersFd[BRANCH_MISSES] > 0) {
147*288bf522SAndroid Build Coastguard Worker mIds[BRANCH_MISSES] = count++;
148*288bf522SAndroid Build Coastguard Worker mEnabledEvents |= EV_BPU_MISSES;
149*288bf522SAndroid Build Coastguard Worker }
150*288bf522SAndroid Build Coastguard Worker }
151*288bf522SAndroid Build Coastguard Worker
152*288bf522SAndroid Build Coastguard Worker #ifdef __ARM_ARCH
153*288bf522SAndroid Build Coastguard Worker if (eventMask & EV_L1I_REFS) {
154*288bf522SAndroid Build Coastguard Worker pe.type = PERF_TYPE_RAW;
155*288bf522SAndroid Build Coastguard Worker pe.config = ARMV8_PMUV3_PERFCTR_L1_ICACHE_ACCESS;
156*288bf522SAndroid Build Coastguard Worker mCountersFd[ICACHE_REFS] = perf_event_open(&pe, 0, -1, groupFd, 0);
157*288bf522SAndroid Build Coastguard Worker if (mCountersFd[ICACHE_REFS] > 0) {
158*288bf522SAndroid Build Coastguard Worker mIds[ICACHE_REFS] = count++;
159*288bf522SAndroid Build Coastguard Worker mEnabledEvents |= EV_L1I_REFS;
160*288bf522SAndroid Build Coastguard Worker }
161*288bf522SAndroid Build Coastguard Worker }
162*288bf522SAndroid Build Coastguard Worker
163*288bf522SAndroid Build Coastguard Worker if (eventMask & EV_L1I_MISSES) {
164*288bf522SAndroid Build Coastguard Worker pe.type = PERF_TYPE_RAW;
165*288bf522SAndroid Build Coastguard Worker pe.config = ARMV8_PMUV3_PERFCTR_L1_ICACHE_REFILL;
166*288bf522SAndroid Build Coastguard Worker mCountersFd[ICACHE_MISSES] = perf_event_open(&pe, 0, -1, groupFd, 0);
167*288bf522SAndroid Build Coastguard Worker if (mCountersFd[ICACHE_MISSES] > 0) {
168*288bf522SAndroid Build Coastguard Worker mIds[ICACHE_MISSES] = count++;
169*288bf522SAndroid Build Coastguard Worker mEnabledEvents |= EV_L1I_MISSES;
170*288bf522SAndroid Build Coastguard Worker }
171*288bf522SAndroid Build Coastguard Worker }
172*288bf522SAndroid Build Coastguard Worker #else
173*288bf522SAndroid Build Coastguard Worker if (eventMask & EV_L1I_REFS) {
174*288bf522SAndroid Build Coastguard Worker pe.type = PERF_TYPE_HW_CACHE;
175*288bf522SAndroid Build Coastguard Worker pe.config = PERF_COUNT_HW_CACHE_L1I |
176*288bf522SAndroid Build Coastguard Worker (PERF_COUNT_HW_CACHE_OP_READ<<8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS<<16);
177*288bf522SAndroid Build Coastguard Worker mCountersFd[ICACHE_REFS] = perf_event_open(&pe, 0, -1, groupFd, 0);
178*288bf522SAndroid Build Coastguard Worker if (mCountersFd[ICACHE_REFS] > 0) {
179*288bf522SAndroid Build Coastguard Worker mIds[ICACHE_REFS] = count++;
180*288bf522SAndroid Build Coastguard Worker mEnabledEvents |= EV_L1I_REFS;
181*288bf522SAndroid Build Coastguard Worker }
182*288bf522SAndroid Build Coastguard Worker }
183*288bf522SAndroid Build Coastguard Worker
184*288bf522SAndroid Build Coastguard Worker if (eventMask & EV_L1I_MISSES) {
185*288bf522SAndroid Build Coastguard Worker pe.type = PERF_TYPE_HW_CACHE;
186*288bf522SAndroid Build Coastguard Worker pe.config = PERF_COUNT_HW_CACHE_L1I |
187*288bf522SAndroid Build Coastguard Worker (PERF_COUNT_HW_CACHE_OP_READ<<8) | (PERF_COUNT_HW_CACHE_RESULT_MISS<<16);
188*288bf522SAndroid Build Coastguard Worker mCountersFd[ICACHE_MISSES] = perf_event_open(&pe, 0, -1, groupFd, 0);
189*288bf522SAndroid Build Coastguard Worker if (mCountersFd[ICACHE_MISSES] > 0) {
190*288bf522SAndroid Build Coastguard Worker mIds[ICACHE_MISSES] = count++;
191*288bf522SAndroid Build Coastguard Worker mEnabledEvents |= EV_L1I_MISSES;
192*288bf522SAndroid Build Coastguard Worker }
193*288bf522SAndroid Build Coastguard Worker }
194*288bf522SAndroid Build Coastguard Worker #endif
195*288bf522SAndroid Build Coastguard Worker }
196*288bf522SAndroid Build Coastguard Worker #endif // __linux__
197*288bf522SAndroid Build Coastguard Worker return mEnabledEvents;
198*288bf522SAndroid Build Coastguard Worker }
199*288bf522SAndroid Build Coastguard Worker
200*288bf522SAndroid Build Coastguard Worker } // namespace utils
201