1*d83cc019SAndroid Build Coastguard Worker /*
2*d83cc019SAndroid Build Coastguard Worker * Copyright © 2007-2019 Intel Corporation
3*d83cc019SAndroid Build Coastguard Worker *
4*d83cc019SAndroid Build Coastguard Worker * Permission is hereby granted, free of charge, to any person obtaining a
5*d83cc019SAndroid Build Coastguard Worker * copy of this software and associated documentation files (the "Software"),
6*d83cc019SAndroid Build Coastguard Worker * to deal in the Software without restriction, including without limitation
7*d83cc019SAndroid Build Coastguard Worker * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*d83cc019SAndroid Build Coastguard Worker * and/or sell copies of the Software, and to permit persons to whom the
9*d83cc019SAndroid Build Coastguard Worker * Software is furnished to do so, subject to the following conditions:
10*d83cc019SAndroid Build Coastguard Worker *
11*d83cc019SAndroid Build Coastguard Worker * The above copyright notice and this permission notice (including the next
12*d83cc019SAndroid Build Coastguard Worker * paragraph) shall be included in all copies or substantial portions of the
13*d83cc019SAndroid Build Coastguard Worker * Software.
14*d83cc019SAndroid Build Coastguard Worker *
15*d83cc019SAndroid Build Coastguard Worker * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*d83cc019SAndroid Build Coastguard Worker * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*d83cc019SAndroid Build Coastguard Worker * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18*d83cc019SAndroid Build Coastguard Worker * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*d83cc019SAndroid Build Coastguard Worker * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20*d83cc019SAndroid Build Coastguard Worker * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21*d83cc019SAndroid Build Coastguard Worker * DEALINGS IN THE SOFTWARE.
22*d83cc019SAndroid Build Coastguard Worker */
23*d83cc019SAndroid Build Coastguard Worker
24*d83cc019SAndroid Build Coastguard Worker #include <stdio.h>
25*d83cc019SAndroid Build Coastguard Worker #include <sys/types.h>
26*d83cc019SAndroid Build Coastguard Worker #include <dirent.h>
27*d83cc019SAndroid Build Coastguard Worker #include <stdint.h>
28*d83cc019SAndroid Build Coastguard Worker #include <assert.h>
29*d83cc019SAndroid Build Coastguard Worker #include <string.h>
30*d83cc019SAndroid Build Coastguard Worker #include <ctype.h>
31*d83cc019SAndroid Build Coastguard Worker #include <stdlib.h>
32*d83cc019SAndroid Build Coastguard Worker #include <unistd.h>
33*d83cc019SAndroid Build Coastguard Worker #include <sys/stat.h>
34*d83cc019SAndroid Build Coastguard Worker #include <fcntl.h>
35*d83cc019SAndroid Build Coastguard Worker #include <inttypes.h>
36*d83cc019SAndroid Build Coastguard Worker #include <sys/ioctl.h>
37*d83cc019SAndroid Build Coastguard Worker #include <errno.h>
38*d83cc019SAndroid Build Coastguard Worker #include <math.h>
39*d83cc019SAndroid Build Coastguard Worker #include <locale.h>
40*d83cc019SAndroid Build Coastguard Worker #include <limits.h>
41*d83cc019SAndroid Build Coastguard Worker #include <signal.h>
42*d83cc019SAndroid Build Coastguard Worker
43*d83cc019SAndroid Build Coastguard Worker #include "igt_perf.h"
44*d83cc019SAndroid Build Coastguard Worker
45*d83cc019SAndroid Build Coastguard Worker struct pmu_pair {
46*d83cc019SAndroid Build Coastguard Worker uint64_t cur;
47*d83cc019SAndroid Build Coastguard Worker uint64_t prev;
48*d83cc019SAndroid Build Coastguard Worker };
49*d83cc019SAndroid Build Coastguard Worker
50*d83cc019SAndroid Build Coastguard Worker struct pmu_counter {
51*d83cc019SAndroid Build Coastguard Worker bool present;
52*d83cc019SAndroid Build Coastguard Worker uint64_t config;
53*d83cc019SAndroid Build Coastguard Worker unsigned int idx;
54*d83cc019SAndroid Build Coastguard Worker struct pmu_pair val;
55*d83cc019SAndroid Build Coastguard Worker };
56*d83cc019SAndroid Build Coastguard Worker
57*d83cc019SAndroid Build Coastguard Worker struct engine {
58*d83cc019SAndroid Build Coastguard Worker const char *name;
59*d83cc019SAndroid Build Coastguard Worker char *display_name;
60*d83cc019SAndroid Build Coastguard Worker char *short_name;
61*d83cc019SAndroid Build Coastguard Worker
62*d83cc019SAndroid Build Coastguard Worker unsigned int class;
63*d83cc019SAndroid Build Coastguard Worker unsigned int instance;
64*d83cc019SAndroid Build Coastguard Worker
65*d83cc019SAndroid Build Coastguard Worker unsigned int num_counters;
66*d83cc019SAndroid Build Coastguard Worker
67*d83cc019SAndroid Build Coastguard Worker struct pmu_counter busy;
68*d83cc019SAndroid Build Coastguard Worker struct pmu_counter wait;
69*d83cc019SAndroid Build Coastguard Worker struct pmu_counter sema;
70*d83cc019SAndroid Build Coastguard Worker };
71*d83cc019SAndroid Build Coastguard Worker
72*d83cc019SAndroid Build Coastguard Worker struct engines {
73*d83cc019SAndroid Build Coastguard Worker unsigned int num_engines;
74*d83cc019SAndroid Build Coastguard Worker unsigned int num_counters;
75*d83cc019SAndroid Build Coastguard Worker DIR *root;
76*d83cc019SAndroid Build Coastguard Worker int fd;
77*d83cc019SAndroid Build Coastguard Worker struct pmu_pair ts;
78*d83cc019SAndroid Build Coastguard Worker
79*d83cc019SAndroid Build Coastguard Worker int rapl_fd;
80*d83cc019SAndroid Build Coastguard Worker double rapl_scale;
81*d83cc019SAndroid Build Coastguard Worker const char *rapl_unit;
82*d83cc019SAndroid Build Coastguard Worker
83*d83cc019SAndroid Build Coastguard Worker int imc_fd;
84*d83cc019SAndroid Build Coastguard Worker double imc_reads_scale;
85*d83cc019SAndroid Build Coastguard Worker const char *imc_reads_unit;
86*d83cc019SAndroid Build Coastguard Worker double imc_writes_scale;
87*d83cc019SAndroid Build Coastguard Worker const char *imc_writes_unit;
88*d83cc019SAndroid Build Coastguard Worker
89*d83cc019SAndroid Build Coastguard Worker struct pmu_counter freq_req;
90*d83cc019SAndroid Build Coastguard Worker struct pmu_counter freq_act;
91*d83cc019SAndroid Build Coastguard Worker struct pmu_counter irq;
92*d83cc019SAndroid Build Coastguard Worker struct pmu_counter rc6;
93*d83cc019SAndroid Build Coastguard Worker struct pmu_counter rapl;
94*d83cc019SAndroid Build Coastguard Worker struct pmu_counter imc_reads;
95*d83cc019SAndroid Build Coastguard Worker struct pmu_counter imc_writes;
96*d83cc019SAndroid Build Coastguard Worker
97*d83cc019SAndroid Build Coastguard Worker struct engine engine;
98*d83cc019SAndroid Build Coastguard Worker };
99*d83cc019SAndroid Build Coastguard Worker
100*d83cc019SAndroid Build Coastguard Worker static uint64_t
get_pmu_config(int dirfd,const char * name,const char * counter)101*d83cc019SAndroid Build Coastguard Worker get_pmu_config(int dirfd, const char *name, const char *counter)
102*d83cc019SAndroid Build Coastguard Worker {
103*d83cc019SAndroid Build Coastguard Worker char buf[128], *p;
104*d83cc019SAndroid Build Coastguard Worker int fd, ret;
105*d83cc019SAndroid Build Coastguard Worker
106*d83cc019SAndroid Build Coastguard Worker ret = snprintf(buf, sizeof(buf), "%s-%s", name, counter);
107*d83cc019SAndroid Build Coastguard Worker if (ret < 0 || ret == sizeof(buf))
108*d83cc019SAndroid Build Coastguard Worker return -1;
109*d83cc019SAndroid Build Coastguard Worker
110*d83cc019SAndroid Build Coastguard Worker fd = openat(dirfd, buf, O_RDONLY);
111*d83cc019SAndroid Build Coastguard Worker if (fd < 0)
112*d83cc019SAndroid Build Coastguard Worker return -1;
113*d83cc019SAndroid Build Coastguard Worker
114*d83cc019SAndroid Build Coastguard Worker ret = read(fd, buf, sizeof(buf));
115*d83cc019SAndroid Build Coastguard Worker close(fd);
116*d83cc019SAndroid Build Coastguard Worker if (ret <= 0)
117*d83cc019SAndroid Build Coastguard Worker return -1;
118*d83cc019SAndroid Build Coastguard Worker
119*d83cc019SAndroid Build Coastguard Worker p = index(buf, '0');
120*d83cc019SAndroid Build Coastguard Worker if (!p)
121*d83cc019SAndroid Build Coastguard Worker return -1;
122*d83cc019SAndroid Build Coastguard Worker
123*d83cc019SAndroid Build Coastguard Worker return strtoul(p, NULL, 0);
124*d83cc019SAndroid Build Coastguard Worker }
125*d83cc019SAndroid Build Coastguard Worker
126*d83cc019SAndroid Build Coastguard Worker #define engine_ptr(engines, n) (&engines->engine + (n))
127*d83cc019SAndroid Build Coastguard Worker
class_display_name(unsigned int class)128*d83cc019SAndroid Build Coastguard Worker static const char *class_display_name(unsigned int class)
129*d83cc019SAndroid Build Coastguard Worker {
130*d83cc019SAndroid Build Coastguard Worker switch (class) {
131*d83cc019SAndroid Build Coastguard Worker case I915_ENGINE_CLASS_RENDER:
132*d83cc019SAndroid Build Coastguard Worker return "Render/3D";
133*d83cc019SAndroid Build Coastguard Worker case I915_ENGINE_CLASS_COPY:
134*d83cc019SAndroid Build Coastguard Worker return "Blitter";
135*d83cc019SAndroid Build Coastguard Worker case I915_ENGINE_CLASS_VIDEO:
136*d83cc019SAndroid Build Coastguard Worker return "Video";
137*d83cc019SAndroid Build Coastguard Worker case I915_ENGINE_CLASS_VIDEO_ENHANCE:
138*d83cc019SAndroid Build Coastguard Worker return "VideoEnhance";
139*d83cc019SAndroid Build Coastguard Worker default:
140*d83cc019SAndroid Build Coastguard Worker return "[unknown]";
141*d83cc019SAndroid Build Coastguard Worker }
142*d83cc019SAndroid Build Coastguard Worker }
143*d83cc019SAndroid Build Coastguard Worker
class_short_name(unsigned int class)144*d83cc019SAndroid Build Coastguard Worker static const char *class_short_name(unsigned int class)
145*d83cc019SAndroid Build Coastguard Worker {
146*d83cc019SAndroid Build Coastguard Worker switch (class) {
147*d83cc019SAndroid Build Coastguard Worker case I915_ENGINE_CLASS_RENDER:
148*d83cc019SAndroid Build Coastguard Worker return "RCS";
149*d83cc019SAndroid Build Coastguard Worker case I915_ENGINE_CLASS_COPY:
150*d83cc019SAndroid Build Coastguard Worker return "BCS";
151*d83cc019SAndroid Build Coastguard Worker case I915_ENGINE_CLASS_VIDEO:
152*d83cc019SAndroid Build Coastguard Worker return "VCS";
153*d83cc019SAndroid Build Coastguard Worker case I915_ENGINE_CLASS_VIDEO_ENHANCE:
154*d83cc019SAndroid Build Coastguard Worker return "VECS";
155*d83cc019SAndroid Build Coastguard Worker default:
156*d83cc019SAndroid Build Coastguard Worker return "UNKN";
157*d83cc019SAndroid Build Coastguard Worker }
158*d83cc019SAndroid Build Coastguard Worker }
159*d83cc019SAndroid Build Coastguard Worker
engine_cmp(const void * __a,const void * __b)160*d83cc019SAndroid Build Coastguard Worker static int engine_cmp(const void *__a, const void *__b)
161*d83cc019SAndroid Build Coastguard Worker {
162*d83cc019SAndroid Build Coastguard Worker const struct engine *a = (struct engine *)__a;
163*d83cc019SAndroid Build Coastguard Worker const struct engine *b = (struct engine *)__b;
164*d83cc019SAndroid Build Coastguard Worker
165*d83cc019SAndroid Build Coastguard Worker if (a->class != b->class)
166*d83cc019SAndroid Build Coastguard Worker return a->class - b->class;
167*d83cc019SAndroid Build Coastguard Worker else
168*d83cc019SAndroid Build Coastguard Worker return a->instance - b->instance;
169*d83cc019SAndroid Build Coastguard Worker }
170*d83cc019SAndroid Build Coastguard Worker
discover_engines(void)171*d83cc019SAndroid Build Coastguard Worker static struct engines *discover_engines(void)
172*d83cc019SAndroid Build Coastguard Worker {
173*d83cc019SAndroid Build Coastguard Worker const char *sysfs_root = "/sys/devices/i915/events";
174*d83cc019SAndroid Build Coastguard Worker struct engines *engines;
175*d83cc019SAndroid Build Coastguard Worker struct dirent *dent;
176*d83cc019SAndroid Build Coastguard Worker int ret = 0;
177*d83cc019SAndroid Build Coastguard Worker DIR *d;
178*d83cc019SAndroid Build Coastguard Worker
179*d83cc019SAndroid Build Coastguard Worker engines = malloc(sizeof(struct engines));
180*d83cc019SAndroid Build Coastguard Worker if (!engines)
181*d83cc019SAndroid Build Coastguard Worker return NULL;
182*d83cc019SAndroid Build Coastguard Worker
183*d83cc019SAndroid Build Coastguard Worker memset(engines, 0, sizeof(*engines));
184*d83cc019SAndroid Build Coastguard Worker
185*d83cc019SAndroid Build Coastguard Worker engines->num_engines = 0;
186*d83cc019SAndroid Build Coastguard Worker
187*d83cc019SAndroid Build Coastguard Worker d = opendir(sysfs_root);
188*d83cc019SAndroid Build Coastguard Worker if (!d)
189*d83cc019SAndroid Build Coastguard Worker return NULL;
190*d83cc019SAndroid Build Coastguard Worker
191*d83cc019SAndroid Build Coastguard Worker while ((dent = readdir(d)) != NULL) {
192*d83cc019SAndroid Build Coastguard Worker const char *endswith = "-busy";
193*d83cc019SAndroid Build Coastguard Worker const unsigned int endlen = strlen(endswith);
194*d83cc019SAndroid Build Coastguard Worker struct engine *engine =
195*d83cc019SAndroid Build Coastguard Worker engine_ptr(engines, engines->num_engines);
196*d83cc019SAndroid Build Coastguard Worker char buf[256];
197*d83cc019SAndroid Build Coastguard Worker
198*d83cc019SAndroid Build Coastguard Worker if (dent->d_type != DT_REG)
199*d83cc019SAndroid Build Coastguard Worker continue;
200*d83cc019SAndroid Build Coastguard Worker
201*d83cc019SAndroid Build Coastguard Worker if (strlen(dent->d_name) >= sizeof(buf)) {
202*d83cc019SAndroid Build Coastguard Worker ret = ENAMETOOLONG;
203*d83cc019SAndroid Build Coastguard Worker break;
204*d83cc019SAndroid Build Coastguard Worker }
205*d83cc019SAndroid Build Coastguard Worker
206*d83cc019SAndroid Build Coastguard Worker strcpy(buf, dent->d_name);
207*d83cc019SAndroid Build Coastguard Worker
208*d83cc019SAndroid Build Coastguard Worker /* xxxN-busy */
209*d83cc019SAndroid Build Coastguard Worker if (strlen(buf) < (endlen + 4))
210*d83cc019SAndroid Build Coastguard Worker continue;
211*d83cc019SAndroid Build Coastguard Worker if (strcmp(&buf[strlen(buf) - endlen], endswith))
212*d83cc019SAndroid Build Coastguard Worker continue;
213*d83cc019SAndroid Build Coastguard Worker
214*d83cc019SAndroid Build Coastguard Worker memset(engine, 0, sizeof(*engine));
215*d83cc019SAndroid Build Coastguard Worker
216*d83cc019SAndroid Build Coastguard Worker buf[strlen(buf) - endlen] = 0;
217*d83cc019SAndroid Build Coastguard Worker engine->name = strdup(buf);
218*d83cc019SAndroid Build Coastguard Worker if (!engine->name) {
219*d83cc019SAndroid Build Coastguard Worker ret = errno;
220*d83cc019SAndroid Build Coastguard Worker break;
221*d83cc019SAndroid Build Coastguard Worker }
222*d83cc019SAndroid Build Coastguard Worker
223*d83cc019SAndroid Build Coastguard Worker engine->busy.config = get_pmu_config(dirfd(d), engine->name,
224*d83cc019SAndroid Build Coastguard Worker "busy");
225*d83cc019SAndroid Build Coastguard Worker if (engine->busy.config == -1) {
226*d83cc019SAndroid Build Coastguard Worker ret = ENOENT;
227*d83cc019SAndroid Build Coastguard Worker break;
228*d83cc019SAndroid Build Coastguard Worker }
229*d83cc019SAndroid Build Coastguard Worker
230*d83cc019SAndroid Build Coastguard Worker engine->class = (engine->busy.config &
231*d83cc019SAndroid Build Coastguard Worker (__I915_PMU_OTHER(0) - 1)) >>
232*d83cc019SAndroid Build Coastguard Worker I915_PMU_CLASS_SHIFT;
233*d83cc019SAndroid Build Coastguard Worker
234*d83cc019SAndroid Build Coastguard Worker engine->instance = (engine->busy.config >>
235*d83cc019SAndroid Build Coastguard Worker I915_PMU_SAMPLE_BITS) &
236*d83cc019SAndroid Build Coastguard Worker ((1 << I915_PMU_SAMPLE_INSTANCE_BITS) - 1);
237*d83cc019SAndroid Build Coastguard Worker
238*d83cc019SAndroid Build Coastguard Worker ret = asprintf(&engine->display_name, "%s/%u",
239*d83cc019SAndroid Build Coastguard Worker class_display_name(engine->class),
240*d83cc019SAndroid Build Coastguard Worker engine->instance);
241*d83cc019SAndroid Build Coastguard Worker if (ret <= 0) {
242*d83cc019SAndroid Build Coastguard Worker ret = errno;
243*d83cc019SAndroid Build Coastguard Worker break;
244*d83cc019SAndroid Build Coastguard Worker }
245*d83cc019SAndroid Build Coastguard Worker
246*d83cc019SAndroid Build Coastguard Worker ret = asprintf(&engine->short_name, "%s/%u",
247*d83cc019SAndroid Build Coastguard Worker class_short_name(engine->class),
248*d83cc019SAndroid Build Coastguard Worker engine->instance);
249*d83cc019SAndroid Build Coastguard Worker if (ret <= 0) {
250*d83cc019SAndroid Build Coastguard Worker ret = errno;
251*d83cc019SAndroid Build Coastguard Worker break;
252*d83cc019SAndroid Build Coastguard Worker }
253*d83cc019SAndroid Build Coastguard Worker
254*d83cc019SAndroid Build Coastguard Worker engines->num_engines++;
255*d83cc019SAndroid Build Coastguard Worker engines = realloc(engines, sizeof(struct engines) +
256*d83cc019SAndroid Build Coastguard Worker engines->num_engines * sizeof(struct engine));
257*d83cc019SAndroid Build Coastguard Worker if (!engines) {
258*d83cc019SAndroid Build Coastguard Worker ret = errno;
259*d83cc019SAndroid Build Coastguard Worker break;
260*d83cc019SAndroid Build Coastguard Worker }
261*d83cc019SAndroid Build Coastguard Worker
262*d83cc019SAndroid Build Coastguard Worker ret = 0;
263*d83cc019SAndroid Build Coastguard Worker }
264*d83cc019SAndroid Build Coastguard Worker
265*d83cc019SAndroid Build Coastguard Worker if (ret) {
266*d83cc019SAndroid Build Coastguard Worker free(engines);
267*d83cc019SAndroid Build Coastguard Worker errno = ret;
268*d83cc019SAndroid Build Coastguard Worker
269*d83cc019SAndroid Build Coastguard Worker return NULL;
270*d83cc019SAndroid Build Coastguard Worker }
271*d83cc019SAndroid Build Coastguard Worker
272*d83cc019SAndroid Build Coastguard Worker qsort(engine_ptr(engines, 0), engines->num_engines,
273*d83cc019SAndroid Build Coastguard Worker sizeof(struct engine), engine_cmp);
274*d83cc019SAndroid Build Coastguard Worker
275*d83cc019SAndroid Build Coastguard Worker engines->root = d;
276*d83cc019SAndroid Build Coastguard Worker
277*d83cc019SAndroid Build Coastguard Worker return engines;
278*d83cc019SAndroid Build Coastguard Worker }
279*d83cc019SAndroid Build Coastguard Worker
280*d83cc019SAndroid Build Coastguard Worker static int
filename_to_buf(const char * filename,char * buf,unsigned int bufsize)281*d83cc019SAndroid Build Coastguard Worker filename_to_buf(const char *filename, char *buf, unsigned int bufsize)
282*d83cc019SAndroid Build Coastguard Worker {
283*d83cc019SAndroid Build Coastguard Worker int fd, err;
284*d83cc019SAndroid Build Coastguard Worker ssize_t ret;
285*d83cc019SAndroid Build Coastguard Worker
286*d83cc019SAndroid Build Coastguard Worker fd = open(filename, O_RDONLY);
287*d83cc019SAndroid Build Coastguard Worker if (fd < 0)
288*d83cc019SAndroid Build Coastguard Worker return -1;
289*d83cc019SAndroid Build Coastguard Worker
290*d83cc019SAndroid Build Coastguard Worker ret = read(fd, buf, bufsize - 1);
291*d83cc019SAndroid Build Coastguard Worker err = errno;
292*d83cc019SAndroid Build Coastguard Worker close(fd);
293*d83cc019SAndroid Build Coastguard Worker if (ret < 1) {
294*d83cc019SAndroid Build Coastguard Worker errno = ret < 0 ? err : ENOMSG;
295*d83cc019SAndroid Build Coastguard Worker
296*d83cc019SAndroid Build Coastguard Worker return -1;
297*d83cc019SAndroid Build Coastguard Worker }
298*d83cc019SAndroid Build Coastguard Worker
299*d83cc019SAndroid Build Coastguard Worker if (ret > 1 && buf[ret - 1] == '\n')
300*d83cc019SAndroid Build Coastguard Worker buf[ret - 1] = '\0';
301*d83cc019SAndroid Build Coastguard Worker else
302*d83cc019SAndroid Build Coastguard Worker buf[ret] = '\0';
303*d83cc019SAndroid Build Coastguard Worker
304*d83cc019SAndroid Build Coastguard Worker return 0;
305*d83cc019SAndroid Build Coastguard Worker }
306*d83cc019SAndroid Build Coastguard Worker
filename_to_u64(const char * filename,int base)307*d83cc019SAndroid Build Coastguard Worker static uint64_t filename_to_u64(const char *filename, int base)
308*d83cc019SAndroid Build Coastguard Worker {
309*d83cc019SAndroid Build Coastguard Worker char buf[64], *b;
310*d83cc019SAndroid Build Coastguard Worker
311*d83cc019SAndroid Build Coastguard Worker if (filename_to_buf(filename, buf, sizeof(buf)))
312*d83cc019SAndroid Build Coastguard Worker return 0;
313*d83cc019SAndroid Build Coastguard Worker
314*d83cc019SAndroid Build Coastguard Worker /*
315*d83cc019SAndroid Build Coastguard Worker * Handle both single integer and key=value formats by skipping
316*d83cc019SAndroid Build Coastguard Worker * leading non-digits.
317*d83cc019SAndroid Build Coastguard Worker */
318*d83cc019SAndroid Build Coastguard Worker b = buf;
319*d83cc019SAndroid Build Coastguard Worker while (*b && !isdigit(*b))
320*d83cc019SAndroid Build Coastguard Worker b++;
321*d83cc019SAndroid Build Coastguard Worker
322*d83cc019SAndroid Build Coastguard Worker return strtoull(b, NULL, base);
323*d83cc019SAndroid Build Coastguard Worker }
324*d83cc019SAndroid Build Coastguard Worker
filename_to_double(const char * filename)325*d83cc019SAndroid Build Coastguard Worker static double filename_to_double(const char *filename)
326*d83cc019SAndroid Build Coastguard Worker {
327*d83cc019SAndroid Build Coastguard Worker char *oldlocale;
328*d83cc019SAndroid Build Coastguard Worker char buf[80];
329*d83cc019SAndroid Build Coastguard Worker double v;
330*d83cc019SAndroid Build Coastguard Worker
331*d83cc019SAndroid Build Coastguard Worker if (filename_to_buf(filename, buf, sizeof(buf)))
332*d83cc019SAndroid Build Coastguard Worker return 0;
333*d83cc019SAndroid Build Coastguard Worker
334*d83cc019SAndroid Build Coastguard Worker oldlocale = setlocale(LC_ALL, "C");
335*d83cc019SAndroid Build Coastguard Worker v = strtod(buf, NULL);
336*d83cc019SAndroid Build Coastguard Worker setlocale(LC_ALL, oldlocale);
337*d83cc019SAndroid Build Coastguard Worker
338*d83cc019SAndroid Build Coastguard Worker return v;
339*d83cc019SAndroid Build Coastguard Worker }
340*d83cc019SAndroid Build Coastguard Worker
341*d83cc019SAndroid Build Coastguard Worker #define RAPL_ROOT "/sys/devices/power/"
342*d83cc019SAndroid Build Coastguard Worker #define RAPL_EVENT "/sys/devices/power/events/"
343*d83cc019SAndroid Build Coastguard Worker
rapl_type_id(void)344*d83cc019SAndroid Build Coastguard Worker static uint64_t rapl_type_id(void)
345*d83cc019SAndroid Build Coastguard Worker {
346*d83cc019SAndroid Build Coastguard Worker return filename_to_u64(RAPL_ROOT "type", 10);
347*d83cc019SAndroid Build Coastguard Worker }
348*d83cc019SAndroid Build Coastguard Worker
rapl_gpu_power(void)349*d83cc019SAndroid Build Coastguard Worker static uint64_t rapl_gpu_power(void)
350*d83cc019SAndroid Build Coastguard Worker {
351*d83cc019SAndroid Build Coastguard Worker return filename_to_u64(RAPL_EVENT "energy-gpu", 0);
352*d83cc019SAndroid Build Coastguard Worker }
353*d83cc019SAndroid Build Coastguard Worker
rapl_gpu_power_scale(void)354*d83cc019SAndroid Build Coastguard Worker static double rapl_gpu_power_scale(void)
355*d83cc019SAndroid Build Coastguard Worker {
356*d83cc019SAndroid Build Coastguard Worker return filename_to_double(RAPL_EVENT "energy-gpu.scale");
357*d83cc019SAndroid Build Coastguard Worker }
358*d83cc019SAndroid Build Coastguard Worker
rapl_gpu_power_unit(void)359*d83cc019SAndroid Build Coastguard Worker static const char *rapl_gpu_power_unit(void)
360*d83cc019SAndroid Build Coastguard Worker {
361*d83cc019SAndroid Build Coastguard Worker char buf[32];
362*d83cc019SAndroid Build Coastguard Worker
363*d83cc019SAndroid Build Coastguard Worker if (filename_to_buf(RAPL_EVENT "energy-gpu.unit",
364*d83cc019SAndroid Build Coastguard Worker buf, sizeof(buf)) == 0)
365*d83cc019SAndroid Build Coastguard Worker if (!strcmp(buf, "Joules"))
366*d83cc019SAndroid Build Coastguard Worker return strdup("Watts");
367*d83cc019SAndroid Build Coastguard Worker else
368*d83cc019SAndroid Build Coastguard Worker return strdup(buf);
369*d83cc019SAndroid Build Coastguard Worker else
370*d83cc019SAndroid Build Coastguard Worker return NULL;
371*d83cc019SAndroid Build Coastguard Worker }
372*d83cc019SAndroid Build Coastguard Worker
373*d83cc019SAndroid Build Coastguard Worker #define IMC_ROOT "/sys/devices/uncore_imc/"
374*d83cc019SAndroid Build Coastguard Worker #define IMC_EVENT "/sys/devices/uncore_imc/events/"
375*d83cc019SAndroid Build Coastguard Worker
imc_type_id(void)376*d83cc019SAndroid Build Coastguard Worker static uint64_t imc_type_id(void)
377*d83cc019SAndroid Build Coastguard Worker {
378*d83cc019SAndroid Build Coastguard Worker return filename_to_u64(IMC_ROOT "type", 10);
379*d83cc019SAndroid Build Coastguard Worker }
380*d83cc019SAndroid Build Coastguard Worker
imc_data_reads(void)381*d83cc019SAndroid Build Coastguard Worker static uint64_t imc_data_reads(void)
382*d83cc019SAndroid Build Coastguard Worker {
383*d83cc019SAndroid Build Coastguard Worker return filename_to_u64(IMC_EVENT "data_reads", 0);
384*d83cc019SAndroid Build Coastguard Worker }
385*d83cc019SAndroid Build Coastguard Worker
imc_data_reads_scale(void)386*d83cc019SAndroid Build Coastguard Worker static double imc_data_reads_scale(void)
387*d83cc019SAndroid Build Coastguard Worker {
388*d83cc019SAndroid Build Coastguard Worker return filename_to_double(IMC_EVENT "data_reads.scale");
389*d83cc019SAndroid Build Coastguard Worker }
390*d83cc019SAndroid Build Coastguard Worker
imc_data_reads_unit(void)391*d83cc019SAndroid Build Coastguard Worker static const char *imc_data_reads_unit(void)
392*d83cc019SAndroid Build Coastguard Worker {
393*d83cc019SAndroid Build Coastguard Worker char buf[32];
394*d83cc019SAndroid Build Coastguard Worker
395*d83cc019SAndroid Build Coastguard Worker if (filename_to_buf(IMC_EVENT "data_reads.unit", buf, sizeof(buf)) == 0)
396*d83cc019SAndroid Build Coastguard Worker return strdup(buf);
397*d83cc019SAndroid Build Coastguard Worker else
398*d83cc019SAndroid Build Coastguard Worker return NULL;
399*d83cc019SAndroid Build Coastguard Worker }
400*d83cc019SAndroid Build Coastguard Worker
imc_data_writes(void)401*d83cc019SAndroid Build Coastguard Worker static uint64_t imc_data_writes(void)
402*d83cc019SAndroid Build Coastguard Worker {
403*d83cc019SAndroid Build Coastguard Worker return filename_to_u64(IMC_EVENT "data_writes", 0);
404*d83cc019SAndroid Build Coastguard Worker }
405*d83cc019SAndroid Build Coastguard Worker
imc_data_writes_scale(void)406*d83cc019SAndroid Build Coastguard Worker static double imc_data_writes_scale(void)
407*d83cc019SAndroid Build Coastguard Worker {
408*d83cc019SAndroid Build Coastguard Worker return filename_to_double(IMC_EVENT "data_writes.scale");
409*d83cc019SAndroid Build Coastguard Worker }
410*d83cc019SAndroid Build Coastguard Worker
imc_data_writes_unit(void)411*d83cc019SAndroid Build Coastguard Worker static const char *imc_data_writes_unit(void)
412*d83cc019SAndroid Build Coastguard Worker {
413*d83cc019SAndroid Build Coastguard Worker char buf[32];
414*d83cc019SAndroid Build Coastguard Worker
415*d83cc019SAndroid Build Coastguard Worker if (filename_to_buf(IMC_EVENT "data_writes.unit",
416*d83cc019SAndroid Build Coastguard Worker buf, sizeof(buf)) == 0)
417*d83cc019SAndroid Build Coastguard Worker return strdup(buf);
418*d83cc019SAndroid Build Coastguard Worker else
419*d83cc019SAndroid Build Coastguard Worker return NULL;
420*d83cc019SAndroid Build Coastguard Worker }
421*d83cc019SAndroid Build Coastguard Worker
422*d83cc019SAndroid Build Coastguard Worker #define _open_pmu(cnt, pmu, fd) \
423*d83cc019SAndroid Build Coastguard Worker ({ \
424*d83cc019SAndroid Build Coastguard Worker int fd__; \
425*d83cc019SAndroid Build Coastguard Worker \
426*d83cc019SAndroid Build Coastguard Worker fd__ = perf_i915_open_group((pmu)->config, (fd)); \
427*d83cc019SAndroid Build Coastguard Worker if (fd__ >= 0) { \
428*d83cc019SAndroid Build Coastguard Worker if ((fd) == -1) \
429*d83cc019SAndroid Build Coastguard Worker (fd) = fd__; \
430*d83cc019SAndroid Build Coastguard Worker (pmu)->present = true; \
431*d83cc019SAndroid Build Coastguard Worker (pmu)->idx = (cnt)++; \
432*d83cc019SAndroid Build Coastguard Worker } \
433*d83cc019SAndroid Build Coastguard Worker \
434*d83cc019SAndroid Build Coastguard Worker fd__; \
435*d83cc019SAndroid Build Coastguard Worker })
436*d83cc019SAndroid Build Coastguard Worker
437*d83cc019SAndroid Build Coastguard Worker #define _open_imc(cnt, pmu, fd) \
438*d83cc019SAndroid Build Coastguard Worker ({ \
439*d83cc019SAndroid Build Coastguard Worker int fd__; \
440*d83cc019SAndroid Build Coastguard Worker \
441*d83cc019SAndroid Build Coastguard Worker fd__ = igt_perf_open_group(imc_type_id(), (pmu)->config, (fd)); \
442*d83cc019SAndroid Build Coastguard Worker if (fd__ >= 0) { \
443*d83cc019SAndroid Build Coastguard Worker if ((fd) == -1) \
444*d83cc019SAndroid Build Coastguard Worker (fd) = fd__; \
445*d83cc019SAndroid Build Coastguard Worker (pmu)->present = true; \
446*d83cc019SAndroid Build Coastguard Worker (pmu)->idx = (cnt)++; \
447*d83cc019SAndroid Build Coastguard Worker } \
448*d83cc019SAndroid Build Coastguard Worker \
449*d83cc019SAndroid Build Coastguard Worker fd__; \
450*d83cc019SAndroid Build Coastguard Worker })
451*d83cc019SAndroid Build Coastguard Worker
pmu_init(struct engines * engines)452*d83cc019SAndroid Build Coastguard Worker static int pmu_init(struct engines *engines)
453*d83cc019SAndroid Build Coastguard Worker {
454*d83cc019SAndroid Build Coastguard Worker unsigned int i;
455*d83cc019SAndroid Build Coastguard Worker int fd;
456*d83cc019SAndroid Build Coastguard Worker
457*d83cc019SAndroid Build Coastguard Worker engines->fd = -1;
458*d83cc019SAndroid Build Coastguard Worker engines->num_counters = 0;
459*d83cc019SAndroid Build Coastguard Worker
460*d83cc019SAndroid Build Coastguard Worker engines->irq.config = I915_PMU_INTERRUPTS;
461*d83cc019SAndroid Build Coastguard Worker fd = _open_pmu(engines->num_counters, &engines->irq, engines->fd);
462*d83cc019SAndroid Build Coastguard Worker if (fd < 0)
463*d83cc019SAndroid Build Coastguard Worker return -1;
464*d83cc019SAndroid Build Coastguard Worker
465*d83cc019SAndroid Build Coastguard Worker engines->freq_req.config = I915_PMU_REQUESTED_FREQUENCY;
466*d83cc019SAndroid Build Coastguard Worker _open_pmu(engines->num_counters, &engines->freq_req, engines->fd);
467*d83cc019SAndroid Build Coastguard Worker
468*d83cc019SAndroid Build Coastguard Worker engines->freq_act.config = I915_PMU_ACTUAL_FREQUENCY;
469*d83cc019SAndroid Build Coastguard Worker _open_pmu(engines->num_counters, &engines->freq_act, engines->fd);
470*d83cc019SAndroid Build Coastguard Worker
471*d83cc019SAndroid Build Coastguard Worker engines->rc6.config = I915_PMU_RC6_RESIDENCY;
472*d83cc019SAndroid Build Coastguard Worker _open_pmu(engines->num_counters, &engines->rc6, engines->fd);
473*d83cc019SAndroid Build Coastguard Worker
474*d83cc019SAndroid Build Coastguard Worker for (i = 0; i < engines->num_engines; i++) {
475*d83cc019SAndroid Build Coastguard Worker struct engine *engine = engine_ptr(engines, i);
476*d83cc019SAndroid Build Coastguard Worker struct {
477*d83cc019SAndroid Build Coastguard Worker struct pmu_counter *pmu;
478*d83cc019SAndroid Build Coastguard Worker const char *counter;
479*d83cc019SAndroid Build Coastguard Worker } *cnt, counters[] = {
480*d83cc019SAndroid Build Coastguard Worker { .pmu = &engine->busy, .counter = "busy" },
481*d83cc019SAndroid Build Coastguard Worker { .pmu = &engine->wait, .counter = "wait" },
482*d83cc019SAndroid Build Coastguard Worker { .pmu = &engine->sema, .counter = "sema" },
483*d83cc019SAndroid Build Coastguard Worker { .pmu = NULL, .counter = NULL },
484*d83cc019SAndroid Build Coastguard Worker };
485*d83cc019SAndroid Build Coastguard Worker
486*d83cc019SAndroid Build Coastguard Worker for (cnt = counters; cnt->pmu; cnt++) {
487*d83cc019SAndroid Build Coastguard Worker if (!cnt->pmu->config)
488*d83cc019SAndroid Build Coastguard Worker cnt->pmu->config =
489*d83cc019SAndroid Build Coastguard Worker get_pmu_config(dirfd(engines->root),
490*d83cc019SAndroid Build Coastguard Worker engine->name,
491*d83cc019SAndroid Build Coastguard Worker cnt->counter);
492*d83cc019SAndroid Build Coastguard Worker fd = _open_pmu(engines->num_counters, cnt->pmu,
493*d83cc019SAndroid Build Coastguard Worker engines->fd);
494*d83cc019SAndroid Build Coastguard Worker if (fd >= 0)
495*d83cc019SAndroid Build Coastguard Worker engine->num_counters++;
496*d83cc019SAndroid Build Coastguard Worker }
497*d83cc019SAndroid Build Coastguard Worker }
498*d83cc019SAndroid Build Coastguard Worker
499*d83cc019SAndroid Build Coastguard Worker engines->rapl_fd = -1;
500*d83cc019SAndroid Build Coastguard Worker if (rapl_type_id()) {
501*d83cc019SAndroid Build Coastguard Worker engines->rapl_scale = rapl_gpu_power_scale();
502*d83cc019SAndroid Build Coastguard Worker engines->rapl_unit = rapl_gpu_power_unit();
503*d83cc019SAndroid Build Coastguard Worker if (!engines->rapl_unit)
504*d83cc019SAndroid Build Coastguard Worker return -1;
505*d83cc019SAndroid Build Coastguard Worker
506*d83cc019SAndroid Build Coastguard Worker engines->rapl.config = rapl_gpu_power();
507*d83cc019SAndroid Build Coastguard Worker if (!engines->rapl.config)
508*d83cc019SAndroid Build Coastguard Worker return -1;
509*d83cc019SAndroid Build Coastguard Worker
510*d83cc019SAndroid Build Coastguard Worker engines->rapl_fd = igt_perf_open(rapl_type_id(),
511*d83cc019SAndroid Build Coastguard Worker engines->rapl.config);
512*d83cc019SAndroid Build Coastguard Worker if (engines->rapl_fd < 0)
513*d83cc019SAndroid Build Coastguard Worker return -1;
514*d83cc019SAndroid Build Coastguard Worker
515*d83cc019SAndroid Build Coastguard Worker engines->rapl.present = true;
516*d83cc019SAndroid Build Coastguard Worker }
517*d83cc019SAndroid Build Coastguard Worker
518*d83cc019SAndroid Build Coastguard Worker engines->imc_fd = -1;
519*d83cc019SAndroid Build Coastguard Worker if (imc_type_id()) {
520*d83cc019SAndroid Build Coastguard Worker unsigned int num = 0;
521*d83cc019SAndroid Build Coastguard Worker
522*d83cc019SAndroid Build Coastguard Worker engines->imc_reads_scale = imc_data_reads_scale();
523*d83cc019SAndroid Build Coastguard Worker engines->imc_writes_scale = imc_data_writes_scale();
524*d83cc019SAndroid Build Coastguard Worker
525*d83cc019SAndroid Build Coastguard Worker engines->imc_reads_unit = imc_data_reads_unit();
526*d83cc019SAndroid Build Coastguard Worker if (!engines->imc_reads_unit)
527*d83cc019SAndroid Build Coastguard Worker return -1;
528*d83cc019SAndroid Build Coastguard Worker
529*d83cc019SAndroid Build Coastguard Worker engines->imc_writes_unit = imc_data_writes_unit();
530*d83cc019SAndroid Build Coastguard Worker if (!engines->imc_writes_unit)
531*d83cc019SAndroid Build Coastguard Worker return -1;
532*d83cc019SAndroid Build Coastguard Worker
533*d83cc019SAndroid Build Coastguard Worker engines->imc_reads.config = imc_data_reads();
534*d83cc019SAndroid Build Coastguard Worker if (!engines->imc_reads.config)
535*d83cc019SAndroid Build Coastguard Worker return -1;
536*d83cc019SAndroid Build Coastguard Worker
537*d83cc019SAndroid Build Coastguard Worker engines->imc_writes.config = imc_data_writes();
538*d83cc019SAndroid Build Coastguard Worker if (!engines->imc_writes.config)
539*d83cc019SAndroid Build Coastguard Worker return -1;
540*d83cc019SAndroid Build Coastguard Worker
541*d83cc019SAndroid Build Coastguard Worker fd = _open_imc(num, &engines->imc_reads, engines->imc_fd);
542*d83cc019SAndroid Build Coastguard Worker if (fd < 0)
543*d83cc019SAndroid Build Coastguard Worker return -1;
544*d83cc019SAndroid Build Coastguard Worker fd = _open_imc(num, &engines->imc_writes, engines->imc_fd);
545*d83cc019SAndroid Build Coastguard Worker if (fd < 0)
546*d83cc019SAndroid Build Coastguard Worker return -1;
547*d83cc019SAndroid Build Coastguard Worker
548*d83cc019SAndroid Build Coastguard Worker engines->imc_reads.present = true;
549*d83cc019SAndroid Build Coastguard Worker engines->imc_writes.present = true;
550*d83cc019SAndroid Build Coastguard Worker }
551*d83cc019SAndroid Build Coastguard Worker
552*d83cc019SAndroid Build Coastguard Worker return 0;
553*d83cc019SAndroid Build Coastguard Worker }
554*d83cc019SAndroid Build Coastguard Worker
pmu_read_multi(int fd,unsigned int num,uint64_t * val)555*d83cc019SAndroid Build Coastguard Worker static uint64_t pmu_read_multi(int fd, unsigned int num, uint64_t *val)
556*d83cc019SAndroid Build Coastguard Worker {
557*d83cc019SAndroid Build Coastguard Worker uint64_t buf[2 + num];
558*d83cc019SAndroid Build Coastguard Worker unsigned int i;
559*d83cc019SAndroid Build Coastguard Worker ssize_t len;
560*d83cc019SAndroid Build Coastguard Worker
561*d83cc019SAndroid Build Coastguard Worker memset(buf, 0, sizeof(buf));
562*d83cc019SAndroid Build Coastguard Worker
563*d83cc019SAndroid Build Coastguard Worker len = read(fd, buf, sizeof(buf));
564*d83cc019SAndroid Build Coastguard Worker assert(len == sizeof(buf));
565*d83cc019SAndroid Build Coastguard Worker
566*d83cc019SAndroid Build Coastguard Worker for (i = 0; i < num; i++)
567*d83cc019SAndroid Build Coastguard Worker val[i] = buf[2 + i];
568*d83cc019SAndroid Build Coastguard Worker
569*d83cc019SAndroid Build Coastguard Worker return buf[1];
570*d83cc019SAndroid Build Coastguard Worker }
571*d83cc019SAndroid Build Coastguard Worker
pmu_calc(struct pmu_pair * p,double d,double t,double s)572*d83cc019SAndroid Build Coastguard Worker static double pmu_calc(struct pmu_pair *p, double d, double t, double s)
573*d83cc019SAndroid Build Coastguard Worker {
574*d83cc019SAndroid Build Coastguard Worker double v;
575*d83cc019SAndroid Build Coastguard Worker
576*d83cc019SAndroid Build Coastguard Worker v = p->cur - p->prev;
577*d83cc019SAndroid Build Coastguard Worker v /= d;
578*d83cc019SAndroid Build Coastguard Worker v /= t;
579*d83cc019SAndroid Build Coastguard Worker v *= s;
580*d83cc019SAndroid Build Coastguard Worker
581*d83cc019SAndroid Build Coastguard Worker if (s == 100.0 && v > 100.0)
582*d83cc019SAndroid Build Coastguard Worker v = 100.0;
583*d83cc019SAndroid Build Coastguard Worker
584*d83cc019SAndroid Build Coastguard Worker return v;
585*d83cc019SAndroid Build Coastguard Worker }
586*d83cc019SAndroid Build Coastguard Worker
fill_str(char * buf,unsigned int bufsz,char c,unsigned int num)587*d83cc019SAndroid Build Coastguard Worker static void fill_str(char *buf, unsigned int bufsz, char c, unsigned int num)
588*d83cc019SAndroid Build Coastguard Worker {
589*d83cc019SAndroid Build Coastguard Worker unsigned int i;
590*d83cc019SAndroid Build Coastguard Worker
591*d83cc019SAndroid Build Coastguard Worker for (i = 0; i < num && i < (bufsz - 1); i++)
592*d83cc019SAndroid Build Coastguard Worker *buf++ = c;
593*d83cc019SAndroid Build Coastguard Worker
594*d83cc019SAndroid Build Coastguard Worker *buf = 0;
595*d83cc019SAndroid Build Coastguard Worker }
596*d83cc019SAndroid Build Coastguard Worker
__pmu_read_single(int fd,uint64_t * ts)597*d83cc019SAndroid Build Coastguard Worker static uint64_t __pmu_read_single(int fd, uint64_t *ts)
598*d83cc019SAndroid Build Coastguard Worker {
599*d83cc019SAndroid Build Coastguard Worker uint64_t data[2] = { };
600*d83cc019SAndroid Build Coastguard Worker ssize_t len;
601*d83cc019SAndroid Build Coastguard Worker
602*d83cc019SAndroid Build Coastguard Worker len = read(fd, data, sizeof(data));
603*d83cc019SAndroid Build Coastguard Worker assert(len == sizeof(data));
604*d83cc019SAndroid Build Coastguard Worker
605*d83cc019SAndroid Build Coastguard Worker if (ts)
606*d83cc019SAndroid Build Coastguard Worker *ts = data[1];
607*d83cc019SAndroid Build Coastguard Worker
608*d83cc019SAndroid Build Coastguard Worker return data[0];
609*d83cc019SAndroid Build Coastguard Worker }
610*d83cc019SAndroid Build Coastguard Worker
pmu_read_single(int fd)611*d83cc019SAndroid Build Coastguard Worker static uint64_t pmu_read_single(int fd)
612*d83cc019SAndroid Build Coastguard Worker {
613*d83cc019SAndroid Build Coastguard Worker return __pmu_read_single(fd, NULL);
614*d83cc019SAndroid Build Coastguard Worker }
615*d83cc019SAndroid Build Coastguard Worker
__update_sample(struct pmu_counter * counter,uint64_t val)616*d83cc019SAndroid Build Coastguard Worker static void __update_sample(struct pmu_counter *counter, uint64_t val)
617*d83cc019SAndroid Build Coastguard Worker {
618*d83cc019SAndroid Build Coastguard Worker counter->val.prev = counter->val.cur;
619*d83cc019SAndroid Build Coastguard Worker counter->val.cur = val;
620*d83cc019SAndroid Build Coastguard Worker }
621*d83cc019SAndroid Build Coastguard Worker
update_sample(struct pmu_counter * counter,uint64_t * val)622*d83cc019SAndroid Build Coastguard Worker static void update_sample(struct pmu_counter *counter, uint64_t *val)
623*d83cc019SAndroid Build Coastguard Worker {
624*d83cc019SAndroid Build Coastguard Worker if (counter->present)
625*d83cc019SAndroid Build Coastguard Worker __update_sample(counter, val[counter->idx]);
626*d83cc019SAndroid Build Coastguard Worker }
627*d83cc019SAndroid Build Coastguard Worker
pmu_sample(struct engines * engines)628*d83cc019SAndroid Build Coastguard Worker static void pmu_sample(struct engines *engines)
629*d83cc019SAndroid Build Coastguard Worker {
630*d83cc019SAndroid Build Coastguard Worker const int num_val = engines->num_counters;
631*d83cc019SAndroid Build Coastguard Worker uint64_t val[2 + num_val];
632*d83cc019SAndroid Build Coastguard Worker unsigned int i;
633*d83cc019SAndroid Build Coastguard Worker
634*d83cc019SAndroid Build Coastguard Worker engines->ts.prev = engines->ts.cur;
635*d83cc019SAndroid Build Coastguard Worker
636*d83cc019SAndroid Build Coastguard Worker if (engines->rapl_fd >= 0)
637*d83cc019SAndroid Build Coastguard Worker __update_sample(&engines->rapl,
638*d83cc019SAndroid Build Coastguard Worker pmu_read_single(engines->rapl_fd));
639*d83cc019SAndroid Build Coastguard Worker
640*d83cc019SAndroid Build Coastguard Worker if (engines->imc_fd >= 0) {
641*d83cc019SAndroid Build Coastguard Worker pmu_read_multi(engines->imc_fd, 2, val);
642*d83cc019SAndroid Build Coastguard Worker update_sample(&engines->imc_reads, val);
643*d83cc019SAndroid Build Coastguard Worker update_sample(&engines->imc_writes, val);
644*d83cc019SAndroid Build Coastguard Worker }
645*d83cc019SAndroid Build Coastguard Worker
646*d83cc019SAndroid Build Coastguard Worker engines->ts.cur = pmu_read_multi(engines->fd, num_val, val);
647*d83cc019SAndroid Build Coastguard Worker
648*d83cc019SAndroid Build Coastguard Worker update_sample(&engines->freq_req, val);
649*d83cc019SAndroid Build Coastguard Worker update_sample(&engines->freq_act, val);
650*d83cc019SAndroid Build Coastguard Worker update_sample(&engines->irq, val);
651*d83cc019SAndroid Build Coastguard Worker update_sample(&engines->rc6, val);
652*d83cc019SAndroid Build Coastguard Worker
653*d83cc019SAndroid Build Coastguard Worker for (i = 0; i < engines->num_engines; i++) {
654*d83cc019SAndroid Build Coastguard Worker struct engine *engine = engine_ptr(engines, i);
655*d83cc019SAndroid Build Coastguard Worker
656*d83cc019SAndroid Build Coastguard Worker update_sample(&engine->busy, val);
657*d83cc019SAndroid Build Coastguard Worker update_sample(&engine->sema, val);
658*d83cc019SAndroid Build Coastguard Worker update_sample(&engine->wait, val);
659*d83cc019SAndroid Build Coastguard Worker }
660*d83cc019SAndroid Build Coastguard Worker }
661*d83cc019SAndroid Build Coastguard Worker
662*d83cc019SAndroid Build Coastguard Worker static const char *bars[] = { " ", "▏", "▎", "▍", "▌", "▋", "▊", "▉", "█" };
663*d83cc019SAndroid Build Coastguard Worker
664*d83cc019SAndroid Build Coastguard Worker static void
print_percentage_bar(double percent,int max_len)665*d83cc019SAndroid Build Coastguard Worker print_percentage_bar(double percent, int max_len)
666*d83cc019SAndroid Build Coastguard Worker {
667*d83cc019SAndroid Build Coastguard Worker int bar_len = percent * (8 * (max_len - 2)) / 100.0;
668*d83cc019SAndroid Build Coastguard Worker int i;
669*d83cc019SAndroid Build Coastguard Worker
670*d83cc019SAndroid Build Coastguard Worker putchar('|');
671*d83cc019SAndroid Build Coastguard Worker
672*d83cc019SAndroid Build Coastguard Worker for (i = bar_len; i >= 8; i -= 8)
673*d83cc019SAndroid Build Coastguard Worker printf("%s", bars[8]);
674*d83cc019SAndroid Build Coastguard Worker if (i)
675*d83cc019SAndroid Build Coastguard Worker printf("%s", bars[i]);
676*d83cc019SAndroid Build Coastguard Worker
677*d83cc019SAndroid Build Coastguard Worker for (i = 0; i < (max_len - 2 - (bar_len + 7) / 8); i++)
678*d83cc019SAndroid Build Coastguard Worker putchar(' ');
679*d83cc019SAndroid Build Coastguard Worker
680*d83cc019SAndroid Build Coastguard Worker putchar('|');
681*d83cc019SAndroid Build Coastguard Worker }
682*d83cc019SAndroid Build Coastguard Worker
683*d83cc019SAndroid Build Coastguard Worker #define DEFAULT_PERIOD_MS (1000)
684*d83cc019SAndroid Build Coastguard Worker
685*d83cc019SAndroid Build Coastguard Worker static void
usage(const char * appname)686*d83cc019SAndroid Build Coastguard Worker usage(const char *appname)
687*d83cc019SAndroid Build Coastguard Worker {
688*d83cc019SAndroid Build Coastguard Worker printf("intel_gpu_top - Display a top-like summary of Intel GPU usage\n"
689*d83cc019SAndroid Build Coastguard Worker "\n"
690*d83cc019SAndroid Build Coastguard Worker "Usage: %s [parameters]\n"
691*d83cc019SAndroid Build Coastguard Worker "\n"
692*d83cc019SAndroid Build Coastguard Worker "\tThe following parameters are optional:\n\n"
693*d83cc019SAndroid Build Coastguard Worker "\t[-h] Show this help text.\n"
694*d83cc019SAndroid Build Coastguard Worker "\t[-J] Output JSON formatted data.\n"
695*d83cc019SAndroid Build Coastguard Worker "\t[-l] List plain text data.\n"
696*d83cc019SAndroid Build Coastguard Worker "\t[-o <file|->] Output to specified file or '-' for standard out.\n"
697*d83cc019SAndroid Build Coastguard Worker "\t[-s <ms>] Refresh period in milliseconds (default %ums).\n"
698*d83cc019SAndroid Build Coastguard Worker "\n",
699*d83cc019SAndroid Build Coastguard Worker appname, DEFAULT_PERIOD_MS);
700*d83cc019SAndroid Build Coastguard Worker }
701*d83cc019SAndroid Build Coastguard Worker
702*d83cc019SAndroid Build Coastguard Worker static enum {
703*d83cc019SAndroid Build Coastguard Worker INTERACTIVE,
704*d83cc019SAndroid Build Coastguard Worker STDOUT,
705*d83cc019SAndroid Build Coastguard Worker JSON
706*d83cc019SAndroid Build Coastguard Worker } output_mode;
707*d83cc019SAndroid Build Coastguard Worker
708*d83cc019SAndroid Build Coastguard Worker struct cnt_item {
709*d83cc019SAndroid Build Coastguard Worker struct pmu_counter *pmu;
710*d83cc019SAndroid Build Coastguard Worker unsigned int fmt_width;
711*d83cc019SAndroid Build Coastguard Worker unsigned int fmt_precision;
712*d83cc019SAndroid Build Coastguard Worker double d;
713*d83cc019SAndroid Build Coastguard Worker double t;
714*d83cc019SAndroid Build Coastguard Worker double s;
715*d83cc019SAndroid Build Coastguard Worker const char *name;
716*d83cc019SAndroid Build Coastguard Worker const char *unit;
717*d83cc019SAndroid Build Coastguard Worker
718*d83cc019SAndroid Build Coastguard Worker /* Internal fields. */
719*d83cc019SAndroid Build Coastguard Worker char buf[16];
720*d83cc019SAndroid Build Coastguard Worker };
721*d83cc019SAndroid Build Coastguard Worker
722*d83cc019SAndroid Build Coastguard Worker struct cnt_group {
723*d83cc019SAndroid Build Coastguard Worker const char *name;
724*d83cc019SAndroid Build Coastguard Worker const char *display_name;
725*d83cc019SAndroid Build Coastguard Worker struct cnt_item *items;
726*d83cc019SAndroid Build Coastguard Worker };
727*d83cc019SAndroid Build Coastguard Worker
728*d83cc019SAndroid Build Coastguard Worker static unsigned int json_indent_level;
729*d83cc019SAndroid Build Coastguard Worker
730*d83cc019SAndroid Build Coastguard Worker static const char *json_indent[] = {
731*d83cc019SAndroid Build Coastguard Worker "",
732*d83cc019SAndroid Build Coastguard Worker "\t",
733*d83cc019SAndroid Build Coastguard Worker "\t\t",
734*d83cc019SAndroid Build Coastguard Worker "\t\t\t",
735*d83cc019SAndroid Build Coastguard Worker "\t\t\t\t",
736*d83cc019SAndroid Build Coastguard Worker "\t\t\t\t\t",
737*d83cc019SAndroid Build Coastguard Worker };
738*d83cc019SAndroid Build Coastguard Worker
739*d83cc019SAndroid Build Coastguard Worker #define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0]))
740*d83cc019SAndroid Build Coastguard Worker
741*d83cc019SAndroid Build Coastguard Worker static unsigned int json_prev_struct_members;
742*d83cc019SAndroid Build Coastguard Worker static unsigned int json_struct_members;
743*d83cc019SAndroid Build Coastguard Worker
744*d83cc019SAndroid Build Coastguard Worker FILE *out;
745*d83cc019SAndroid Build Coastguard Worker
746*d83cc019SAndroid Build Coastguard Worker static void
json_open_struct(const char * name)747*d83cc019SAndroid Build Coastguard Worker json_open_struct(const char *name)
748*d83cc019SAndroid Build Coastguard Worker {
749*d83cc019SAndroid Build Coastguard Worker assert(json_indent_level < ARRAY_SIZE(json_indent));
750*d83cc019SAndroid Build Coastguard Worker
751*d83cc019SAndroid Build Coastguard Worker json_prev_struct_members = json_struct_members;
752*d83cc019SAndroid Build Coastguard Worker json_struct_members = 0;
753*d83cc019SAndroid Build Coastguard Worker
754*d83cc019SAndroid Build Coastguard Worker if (name)
755*d83cc019SAndroid Build Coastguard Worker fprintf(out, "%s%s\"%s\": {\n",
756*d83cc019SAndroid Build Coastguard Worker json_prev_struct_members ? ",\n" : "",
757*d83cc019SAndroid Build Coastguard Worker json_indent[json_indent_level],
758*d83cc019SAndroid Build Coastguard Worker name);
759*d83cc019SAndroid Build Coastguard Worker else
760*d83cc019SAndroid Build Coastguard Worker fprintf(out, "%s\n%s{\n",
761*d83cc019SAndroid Build Coastguard Worker json_prev_struct_members ? "," : "",
762*d83cc019SAndroid Build Coastguard Worker json_indent[json_indent_level]);
763*d83cc019SAndroid Build Coastguard Worker
764*d83cc019SAndroid Build Coastguard Worker json_indent_level++;
765*d83cc019SAndroid Build Coastguard Worker }
766*d83cc019SAndroid Build Coastguard Worker
767*d83cc019SAndroid Build Coastguard Worker static void
json_close_struct(void)768*d83cc019SAndroid Build Coastguard Worker json_close_struct(void)
769*d83cc019SAndroid Build Coastguard Worker {
770*d83cc019SAndroid Build Coastguard Worker assert(json_indent_level > 0);
771*d83cc019SAndroid Build Coastguard Worker
772*d83cc019SAndroid Build Coastguard Worker fprintf(out, "\n%s}", json_indent[--json_indent_level]);
773*d83cc019SAndroid Build Coastguard Worker
774*d83cc019SAndroid Build Coastguard Worker if (json_indent_level == 0)
775*d83cc019SAndroid Build Coastguard Worker fflush(stdout);
776*d83cc019SAndroid Build Coastguard Worker }
777*d83cc019SAndroid Build Coastguard Worker
778*d83cc019SAndroid Build Coastguard Worker static unsigned int
json_add_member(const struct cnt_group * parent,struct cnt_item * item,unsigned int headers)779*d83cc019SAndroid Build Coastguard Worker json_add_member(const struct cnt_group *parent, struct cnt_item *item,
780*d83cc019SAndroid Build Coastguard Worker unsigned int headers)
781*d83cc019SAndroid Build Coastguard Worker {
782*d83cc019SAndroid Build Coastguard Worker assert(json_indent_level < ARRAY_SIZE(json_indent));
783*d83cc019SAndroid Build Coastguard Worker
784*d83cc019SAndroid Build Coastguard Worker fprintf(out, "%s%s\"%s\": ",
785*d83cc019SAndroid Build Coastguard Worker json_struct_members ? ",\n" : "",
786*d83cc019SAndroid Build Coastguard Worker json_indent[json_indent_level], item->name);
787*d83cc019SAndroid Build Coastguard Worker
788*d83cc019SAndroid Build Coastguard Worker json_struct_members++;
789*d83cc019SAndroid Build Coastguard Worker
790*d83cc019SAndroid Build Coastguard Worker if (!strcmp(item->name, "unit"))
791*d83cc019SAndroid Build Coastguard Worker fprintf(out, "\"%s\"", item->unit);
792*d83cc019SAndroid Build Coastguard Worker else
793*d83cc019SAndroid Build Coastguard Worker fprintf(out, "%f",
794*d83cc019SAndroid Build Coastguard Worker pmu_calc(&item->pmu->val, item->d, item->t, item->s));
795*d83cc019SAndroid Build Coastguard Worker
796*d83cc019SAndroid Build Coastguard Worker return 1;
797*d83cc019SAndroid Build Coastguard Worker }
798*d83cc019SAndroid Build Coastguard Worker
799*d83cc019SAndroid Build Coastguard Worker static unsigned int stdout_level;
800*d83cc019SAndroid Build Coastguard Worker
801*d83cc019SAndroid Build Coastguard Worker #define STDOUT_HEADER_REPEAT 20
802*d83cc019SAndroid Build Coastguard Worker static unsigned int stdout_lines = STDOUT_HEADER_REPEAT;
803*d83cc019SAndroid Build Coastguard Worker
804*d83cc019SAndroid Build Coastguard Worker static void
stdout_open_struct(const char * name)805*d83cc019SAndroid Build Coastguard Worker stdout_open_struct(const char *name)
806*d83cc019SAndroid Build Coastguard Worker {
807*d83cc019SAndroid Build Coastguard Worker stdout_level++;
808*d83cc019SAndroid Build Coastguard Worker assert(stdout_level > 0);
809*d83cc019SAndroid Build Coastguard Worker }
810*d83cc019SAndroid Build Coastguard Worker
811*d83cc019SAndroid Build Coastguard Worker static void
stdout_close_struct(void)812*d83cc019SAndroid Build Coastguard Worker stdout_close_struct(void)
813*d83cc019SAndroid Build Coastguard Worker {
814*d83cc019SAndroid Build Coastguard Worker assert(stdout_level > 0);
815*d83cc019SAndroid Build Coastguard Worker if (--stdout_level == 0) {
816*d83cc019SAndroid Build Coastguard Worker stdout_lines++;
817*d83cc019SAndroid Build Coastguard Worker fputs("\n", out);
818*d83cc019SAndroid Build Coastguard Worker fflush(out);
819*d83cc019SAndroid Build Coastguard Worker }
820*d83cc019SAndroid Build Coastguard Worker }
821*d83cc019SAndroid Build Coastguard Worker
822*d83cc019SAndroid Build Coastguard Worker static unsigned int
stdout_add_member(const struct cnt_group * parent,struct cnt_item * item,unsigned int headers)823*d83cc019SAndroid Build Coastguard Worker stdout_add_member(const struct cnt_group *parent, struct cnt_item *item,
824*d83cc019SAndroid Build Coastguard Worker unsigned int headers)
825*d83cc019SAndroid Build Coastguard Worker {
826*d83cc019SAndroid Build Coastguard Worker unsigned int fmt_tot = item->fmt_width + (item->fmt_precision ? 1 : 0);
827*d83cc019SAndroid Build Coastguard Worker char buf[fmt_tot + 1];
828*d83cc019SAndroid Build Coastguard Worker double val;
829*d83cc019SAndroid Build Coastguard Worker int len;
830*d83cc019SAndroid Build Coastguard Worker
831*d83cc019SAndroid Build Coastguard Worker if (!item->pmu)
832*d83cc019SAndroid Build Coastguard Worker return 0;
833*d83cc019SAndroid Build Coastguard Worker else if (!item->pmu->present)
834*d83cc019SAndroid Build Coastguard Worker return 0;
835*d83cc019SAndroid Build Coastguard Worker
836*d83cc019SAndroid Build Coastguard Worker if (headers == 1) {
837*d83cc019SAndroid Build Coastguard Worker unsigned int grp_tot = 0;
838*d83cc019SAndroid Build Coastguard Worker struct cnt_item *it;
839*d83cc019SAndroid Build Coastguard Worker
840*d83cc019SAndroid Build Coastguard Worker if (item != parent->items)
841*d83cc019SAndroid Build Coastguard Worker return 0;
842*d83cc019SAndroid Build Coastguard Worker
843*d83cc019SAndroid Build Coastguard Worker for (it = parent->items; it->pmu; it++) {
844*d83cc019SAndroid Build Coastguard Worker if (!it->pmu->present)
845*d83cc019SAndroid Build Coastguard Worker continue;
846*d83cc019SAndroid Build Coastguard Worker
847*d83cc019SAndroid Build Coastguard Worker grp_tot += 1 + it->fmt_width +
848*d83cc019SAndroid Build Coastguard Worker (it->fmt_precision ? 1 : 0);
849*d83cc019SAndroid Build Coastguard Worker }
850*d83cc019SAndroid Build Coastguard Worker
851*d83cc019SAndroid Build Coastguard Worker fprintf(out, "%*s ", grp_tot - 1, parent->display_name);
852*d83cc019SAndroid Build Coastguard Worker return 0;
853*d83cc019SAndroid Build Coastguard Worker } else if (headers == 2) {
854*d83cc019SAndroid Build Coastguard Worker fprintf(out, "%*s ", fmt_tot, item->unit ?: item->name);
855*d83cc019SAndroid Build Coastguard Worker return 0;
856*d83cc019SAndroid Build Coastguard Worker }
857*d83cc019SAndroid Build Coastguard Worker
858*d83cc019SAndroid Build Coastguard Worker val = pmu_calc(&item->pmu->val, item->d, item->t, item->s);
859*d83cc019SAndroid Build Coastguard Worker
860*d83cc019SAndroid Build Coastguard Worker len = snprintf(buf, sizeof(buf), "%*.*f",
861*d83cc019SAndroid Build Coastguard Worker fmt_tot, item->fmt_precision, val);
862*d83cc019SAndroid Build Coastguard Worker if (len < 0 || len == sizeof(buf))
863*d83cc019SAndroid Build Coastguard Worker fill_str(buf, sizeof(buf), 'X', fmt_tot);
864*d83cc019SAndroid Build Coastguard Worker
865*d83cc019SAndroid Build Coastguard Worker len = fprintf(out, "%s ", buf);
866*d83cc019SAndroid Build Coastguard Worker
867*d83cc019SAndroid Build Coastguard Worker return len > 0 ? len : 0;
868*d83cc019SAndroid Build Coastguard Worker }
869*d83cc019SAndroid Build Coastguard Worker
870*d83cc019SAndroid Build Coastguard Worker static void
term_open_struct(const char * name)871*d83cc019SAndroid Build Coastguard Worker term_open_struct(const char *name)
872*d83cc019SAndroid Build Coastguard Worker {
873*d83cc019SAndroid Build Coastguard Worker }
874*d83cc019SAndroid Build Coastguard Worker
875*d83cc019SAndroid Build Coastguard Worker static void
term_close_struct(void)876*d83cc019SAndroid Build Coastguard Worker term_close_struct(void)
877*d83cc019SAndroid Build Coastguard Worker {
878*d83cc019SAndroid Build Coastguard Worker }
879*d83cc019SAndroid Build Coastguard Worker
880*d83cc019SAndroid Build Coastguard Worker static unsigned int
term_add_member(const struct cnt_group * parent,struct cnt_item * item,unsigned int headers)881*d83cc019SAndroid Build Coastguard Worker term_add_member(const struct cnt_group *parent, struct cnt_item *item,
882*d83cc019SAndroid Build Coastguard Worker unsigned int headers)
883*d83cc019SAndroid Build Coastguard Worker {
884*d83cc019SAndroid Build Coastguard Worker unsigned int fmt_tot = item->fmt_width + (item->fmt_precision ? 1 : 0);
885*d83cc019SAndroid Build Coastguard Worker double val;
886*d83cc019SAndroid Build Coastguard Worker int len;
887*d83cc019SAndroid Build Coastguard Worker
888*d83cc019SAndroid Build Coastguard Worker if (!item->pmu)
889*d83cc019SAndroid Build Coastguard Worker return 0;
890*d83cc019SAndroid Build Coastguard Worker
891*d83cc019SAndroid Build Coastguard Worker assert(fmt_tot <= sizeof(item->buf));
892*d83cc019SAndroid Build Coastguard Worker
893*d83cc019SAndroid Build Coastguard Worker if (!item->pmu->present) {
894*d83cc019SAndroid Build Coastguard Worker fill_str(item->buf, sizeof(item->buf), '-', fmt_tot);
895*d83cc019SAndroid Build Coastguard Worker return 1;
896*d83cc019SAndroid Build Coastguard Worker }
897*d83cc019SAndroid Build Coastguard Worker
898*d83cc019SAndroid Build Coastguard Worker val = pmu_calc(&item->pmu->val, item->d, item->t, item->s);
899*d83cc019SAndroid Build Coastguard Worker len = snprintf(item->buf, sizeof(item->buf),
900*d83cc019SAndroid Build Coastguard Worker "%*.*f",
901*d83cc019SAndroid Build Coastguard Worker fmt_tot, item->fmt_precision, val);
902*d83cc019SAndroid Build Coastguard Worker
903*d83cc019SAndroid Build Coastguard Worker if (len < 0 || len == sizeof(item->buf))
904*d83cc019SAndroid Build Coastguard Worker fill_str(item->buf, sizeof(item->buf), 'X', fmt_tot);
905*d83cc019SAndroid Build Coastguard Worker
906*d83cc019SAndroid Build Coastguard Worker return 1;
907*d83cc019SAndroid Build Coastguard Worker }
908*d83cc019SAndroid Build Coastguard Worker
909*d83cc019SAndroid Build Coastguard Worker struct print_operations {
910*d83cc019SAndroid Build Coastguard Worker void (*open_struct)(const char *name);
911*d83cc019SAndroid Build Coastguard Worker void (*close_struct)(void);
912*d83cc019SAndroid Build Coastguard Worker unsigned int (*add_member)(const struct cnt_group *parent,
913*d83cc019SAndroid Build Coastguard Worker struct cnt_item *item,
914*d83cc019SAndroid Build Coastguard Worker unsigned int headers);
915*d83cc019SAndroid Build Coastguard Worker bool (*print_group)(struct cnt_group *group, unsigned int headers);
916*d83cc019SAndroid Build Coastguard Worker };
917*d83cc019SAndroid Build Coastguard Worker
918*d83cc019SAndroid Build Coastguard Worker static const struct print_operations *pops;
919*d83cc019SAndroid Build Coastguard Worker
920*d83cc019SAndroid Build Coastguard Worker static unsigned int
present_in_group(const struct cnt_group * grp)921*d83cc019SAndroid Build Coastguard Worker present_in_group(const struct cnt_group *grp)
922*d83cc019SAndroid Build Coastguard Worker {
923*d83cc019SAndroid Build Coastguard Worker unsigned int present = 0;
924*d83cc019SAndroid Build Coastguard Worker struct cnt_item *item;
925*d83cc019SAndroid Build Coastguard Worker
926*d83cc019SAndroid Build Coastguard Worker for (item = grp->items; item->name; item++) {
927*d83cc019SAndroid Build Coastguard Worker if (item->pmu && item->pmu->present)
928*d83cc019SAndroid Build Coastguard Worker present++;
929*d83cc019SAndroid Build Coastguard Worker }
930*d83cc019SAndroid Build Coastguard Worker
931*d83cc019SAndroid Build Coastguard Worker return present;
932*d83cc019SAndroid Build Coastguard Worker }
933*d83cc019SAndroid Build Coastguard Worker
934*d83cc019SAndroid Build Coastguard Worker static bool
print_group(struct cnt_group * grp,unsigned int headers)935*d83cc019SAndroid Build Coastguard Worker print_group(struct cnt_group *grp, unsigned int headers)
936*d83cc019SAndroid Build Coastguard Worker {
937*d83cc019SAndroid Build Coastguard Worker unsigned int consumed = 0;
938*d83cc019SAndroid Build Coastguard Worker struct cnt_item *item;
939*d83cc019SAndroid Build Coastguard Worker
940*d83cc019SAndroid Build Coastguard Worker if (!present_in_group(grp))
941*d83cc019SAndroid Build Coastguard Worker return false;
942*d83cc019SAndroid Build Coastguard Worker
943*d83cc019SAndroid Build Coastguard Worker pops->open_struct(grp->name);
944*d83cc019SAndroid Build Coastguard Worker
945*d83cc019SAndroid Build Coastguard Worker for (item = grp->items; item->name; item++)
946*d83cc019SAndroid Build Coastguard Worker consumed += pops->add_member(grp, item, headers);
947*d83cc019SAndroid Build Coastguard Worker
948*d83cc019SAndroid Build Coastguard Worker pops->close_struct();
949*d83cc019SAndroid Build Coastguard Worker
950*d83cc019SAndroid Build Coastguard Worker return consumed;
951*d83cc019SAndroid Build Coastguard Worker }
952*d83cc019SAndroid Build Coastguard Worker
953*d83cc019SAndroid Build Coastguard Worker static bool
term_print_group(struct cnt_group * grp,unsigned int headers)954*d83cc019SAndroid Build Coastguard Worker term_print_group(struct cnt_group *grp, unsigned int headers)
955*d83cc019SAndroid Build Coastguard Worker {
956*d83cc019SAndroid Build Coastguard Worker unsigned int consumed = 0;
957*d83cc019SAndroid Build Coastguard Worker struct cnt_item *item;
958*d83cc019SAndroid Build Coastguard Worker
959*d83cc019SAndroid Build Coastguard Worker pops->open_struct(grp->name);
960*d83cc019SAndroid Build Coastguard Worker
961*d83cc019SAndroid Build Coastguard Worker for (item = grp->items; item->name; item++)
962*d83cc019SAndroid Build Coastguard Worker consumed += pops->add_member(grp, item, headers);
963*d83cc019SAndroid Build Coastguard Worker
964*d83cc019SAndroid Build Coastguard Worker pops->close_struct();
965*d83cc019SAndroid Build Coastguard Worker
966*d83cc019SAndroid Build Coastguard Worker return consumed;
967*d83cc019SAndroid Build Coastguard Worker }
968*d83cc019SAndroid Build Coastguard Worker
969*d83cc019SAndroid Build Coastguard Worker static const struct print_operations json_pops = {
970*d83cc019SAndroid Build Coastguard Worker .open_struct = json_open_struct,
971*d83cc019SAndroid Build Coastguard Worker .close_struct = json_close_struct,
972*d83cc019SAndroid Build Coastguard Worker .add_member = json_add_member,
973*d83cc019SAndroid Build Coastguard Worker .print_group = print_group,
974*d83cc019SAndroid Build Coastguard Worker };
975*d83cc019SAndroid Build Coastguard Worker
976*d83cc019SAndroid Build Coastguard Worker static const struct print_operations stdout_pops = {
977*d83cc019SAndroid Build Coastguard Worker .open_struct = stdout_open_struct,
978*d83cc019SAndroid Build Coastguard Worker .close_struct = stdout_close_struct,
979*d83cc019SAndroid Build Coastguard Worker .add_member = stdout_add_member,
980*d83cc019SAndroid Build Coastguard Worker .print_group = print_group,
981*d83cc019SAndroid Build Coastguard Worker };
982*d83cc019SAndroid Build Coastguard Worker
983*d83cc019SAndroid Build Coastguard Worker static const struct print_operations term_pops = {
984*d83cc019SAndroid Build Coastguard Worker .open_struct = term_open_struct,
985*d83cc019SAndroid Build Coastguard Worker .close_struct = term_close_struct,
986*d83cc019SAndroid Build Coastguard Worker .add_member = term_add_member,
987*d83cc019SAndroid Build Coastguard Worker .print_group = term_print_group,
988*d83cc019SAndroid Build Coastguard Worker };
989*d83cc019SAndroid Build Coastguard Worker
print_groups(struct cnt_group ** groups)990*d83cc019SAndroid Build Coastguard Worker static bool print_groups(struct cnt_group **groups)
991*d83cc019SAndroid Build Coastguard Worker {
992*d83cc019SAndroid Build Coastguard Worker unsigned int headers = stdout_lines % STDOUT_HEADER_REPEAT + 1;
993*d83cc019SAndroid Build Coastguard Worker bool print_data = true;
994*d83cc019SAndroid Build Coastguard Worker
995*d83cc019SAndroid Build Coastguard Worker if (output_mode == STDOUT && (headers == 1 || headers == 2)) {
996*d83cc019SAndroid Build Coastguard Worker for (struct cnt_group **grp = groups; *grp; grp++)
997*d83cc019SAndroid Build Coastguard Worker print_data = pops->print_group(*grp, headers);
998*d83cc019SAndroid Build Coastguard Worker }
999*d83cc019SAndroid Build Coastguard Worker
1000*d83cc019SAndroid Build Coastguard Worker for (struct cnt_group **grp = groups; print_data && *grp; grp++)
1001*d83cc019SAndroid Build Coastguard Worker pops->print_group(*grp, false);
1002*d83cc019SAndroid Build Coastguard Worker
1003*d83cc019SAndroid Build Coastguard Worker return print_data;
1004*d83cc019SAndroid Build Coastguard Worker }
1005*d83cc019SAndroid Build Coastguard Worker
1006*d83cc019SAndroid Build Coastguard Worker static int
print_header(struct engines * engines,double t,int lines,int con_w,int con_h,bool * consumed)1007*d83cc019SAndroid Build Coastguard Worker print_header(struct engines *engines, double t,
1008*d83cc019SAndroid Build Coastguard Worker int lines, int con_w, int con_h, bool *consumed)
1009*d83cc019SAndroid Build Coastguard Worker {
1010*d83cc019SAndroid Build Coastguard Worker struct pmu_counter fake_pmu = {
1011*d83cc019SAndroid Build Coastguard Worker .present = true,
1012*d83cc019SAndroid Build Coastguard Worker .val.cur = 1,
1013*d83cc019SAndroid Build Coastguard Worker };
1014*d83cc019SAndroid Build Coastguard Worker struct cnt_item period_items[] = {
1015*d83cc019SAndroid Build Coastguard Worker { &fake_pmu, 0, 0, 1.0, 1.0, t * 1e3, "duration" },
1016*d83cc019SAndroid Build Coastguard Worker { NULL, 0, 0, 0.0, 0.0, 0.0, "unit", "ms" },
1017*d83cc019SAndroid Build Coastguard Worker { },
1018*d83cc019SAndroid Build Coastguard Worker };
1019*d83cc019SAndroid Build Coastguard Worker struct cnt_group period_group = {
1020*d83cc019SAndroid Build Coastguard Worker .name = "period",
1021*d83cc019SAndroid Build Coastguard Worker .items = period_items,
1022*d83cc019SAndroid Build Coastguard Worker };
1023*d83cc019SAndroid Build Coastguard Worker struct cnt_item freq_items[] = {
1024*d83cc019SAndroid Build Coastguard Worker { &engines->freq_req, 4, 0, 1.0, t, 1, "requested", "req" },
1025*d83cc019SAndroid Build Coastguard Worker { &engines->freq_act, 4, 0, 1.0, t, 1, "actual", "act" },
1026*d83cc019SAndroid Build Coastguard Worker { NULL, 0, 0, 0.0, 0.0, 0.0, "unit", "MHz" },
1027*d83cc019SAndroid Build Coastguard Worker { },
1028*d83cc019SAndroid Build Coastguard Worker };
1029*d83cc019SAndroid Build Coastguard Worker struct cnt_group freq_group = {
1030*d83cc019SAndroid Build Coastguard Worker .name = "frequency",
1031*d83cc019SAndroid Build Coastguard Worker .display_name = "Freq MHz",
1032*d83cc019SAndroid Build Coastguard Worker .items = freq_items,
1033*d83cc019SAndroid Build Coastguard Worker };
1034*d83cc019SAndroid Build Coastguard Worker struct cnt_item irq_items[] = {
1035*d83cc019SAndroid Build Coastguard Worker { &engines->irq, 8, 0, 1.0, t, 1, "count", "/s" },
1036*d83cc019SAndroid Build Coastguard Worker { NULL, 0, 0, 0.0, 0.0, 0.0, "unit", "irq/s" },
1037*d83cc019SAndroid Build Coastguard Worker { },
1038*d83cc019SAndroid Build Coastguard Worker };
1039*d83cc019SAndroid Build Coastguard Worker struct cnt_group irq_group = {
1040*d83cc019SAndroid Build Coastguard Worker .name = "interrupts",
1041*d83cc019SAndroid Build Coastguard Worker .display_name = "IRQ",
1042*d83cc019SAndroid Build Coastguard Worker .items = irq_items,
1043*d83cc019SAndroid Build Coastguard Worker };
1044*d83cc019SAndroid Build Coastguard Worker struct cnt_item rc6_items[] = {
1045*d83cc019SAndroid Build Coastguard Worker { &engines->rc6, 3, 0, 1e9, t, 100, "value", "%" },
1046*d83cc019SAndroid Build Coastguard Worker { NULL, 0, 0, 0.0, 0.0, 0.0, "unit", "%" },
1047*d83cc019SAndroid Build Coastguard Worker { },
1048*d83cc019SAndroid Build Coastguard Worker };
1049*d83cc019SAndroid Build Coastguard Worker struct cnt_group rc6_group = {
1050*d83cc019SAndroid Build Coastguard Worker .name = "rc6",
1051*d83cc019SAndroid Build Coastguard Worker .display_name = "RC6",
1052*d83cc019SAndroid Build Coastguard Worker .items = rc6_items,
1053*d83cc019SAndroid Build Coastguard Worker };
1054*d83cc019SAndroid Build Coastguard Worker struct cnt_item power_items[] = {
1055*d83cc019SAndroid Build Coastguard Worker { &engines->rapl, 4, 2, 1.0, t, engines->rapl_scale, "value",
1056*d83cc019SAndroid Build Coastguard Worker "W" },
1057*d83cc019SAndroid Build Coastguard Worker { NULL, 0, 0, 0.0, 0.0, 0.0, "unit", "W" },
1058*d83cc019SAndroid Build Coastguard Worker { },
1059*d83cc019SAndroid Build Coastguard Worker };
1060*d83cc019SAndroid Build Coastguard Worker struct cnt_group power_group = {
1061*d83cc019SAndroid Build Coastguard Worker .name = "power",
1062*d83cc019SAndroid Build Coastguard Worker .display_name = "Power",
1063*d83cc019SAndroid Build Coastguard Worker .items = power_items,
1064*d83cc019SAndroid Build Coastguard Worker };
1065*d83cc019SAndroid Build Coastguard Worker struct cnt_group *groups[] = {
1066*d83cc019SAndroid Build Coastguard Worker &period_group,
1067*d83cc019SAndroid Build Coastguard Worker &freq_group,
1068*d83cc019SAndroid Build Coastguard Worker &irq_group,
1069*d83cc019SAndroid Build Coastguard Worker &rc6_group,
1070*d83cc019SAndroid Build Coastguard Worker &power_group,
1071*d83cc019SAndroid Build Coastguard Worker NULL
1072*d83cc019SAndroid Build Coastguard Worker };
1073*d83cc019SAndroid Build Coastguard Worker
1074*d83cc019SAndroid Build Coastguard Worker if (output_mode != JSON)
1075*d83cc019SAndroid Build Coastguard Worker memmove(&groups[0], &groups[1],
1076*d83cc019SAndroid Build Coastguard Worker sizeof(groups) - sizeof(groups[0]));
1077*d83cc019SAndroid Build Coastguard Worker
1078*d83cc019SAndroid Build Coastguard Worker pops->open_struct(NULL);
1079*d83cc019SAndroid Build Coastguard Worker
1080*d83cc019SAndroid Build Coastguard Worker *consumed = print_groups(groups);
1081*d83cc019SAndroid Build Coastguard Worker
1082*d83cc019SAndroid Build Coastguard Worker if (output_mode == INTERACTIVE) {
1083*d83cc019SAndroid Build Coastguard Worker printf("\033[H\033[J");
1084*d83cc019SAndroid Build Coastguard Worker
1085*d83cc019SAndroid Build Coastguard Worker if (lines++ < con_h)
1086*d83cc019SAndroid Build Coastguard Worker printf("intel-gpu-top - %s/%s MHz; %s%% RC6; %s %s; %s irqs/s\n",
1087*d83cc019SAndroid Build Coastguard Worker freq_items[1].buf, freq_items[0].buf,
1088*d83cc019SAndroid Build Coastguard Worker rc6_items[0].buf, power_items[0].buf,
1089*d83cc019SAndroid Build Coastguard Worker engines->rapl_unit,
1090*d83cc019SAndroid Build Coastguard Worker irq_items[0].buf);
1091*d83cc019SAndroid Build Coastguard Worker
1092*d83cc019SAndroid Build Coastguard Worker if (lines++ < con_h)
1093*d83cc019SAndroid Build Coastguard Worker printf("\n");
1094*d83cc019SAndroid Build Coastguard Worker }
1095*d83cc019SAndroid Build Coastguard Worker
1096*d83cc019SAndroid Build Coastguard Worker return lines;
1097*d83cc019SAndroid Build Coastguard Worker }
1098*d83cc019SAndroid Build Coastguard Worker
1099*d83cc019SAndroid Build Coastguard Worker static int
print_imc(struct engines * engines,double t,int lines,int con_w,int con_h)1100*d83cc019SAndroid Build Coastguard Worker print_imc(struct engines *engines, double t, int lines, int con_w, int con_h)
1101*d83cc019SAndroid Build Coastguard Worker {
1102*d83cc019SAndroid Build Coastguard Worker struct cnt_item imc_items[] = {
1103*d83cc019SAndroid Build Coastguard Worker { &engines->imc_reads, 6, 0, 1.0, t, engines->imc_reads_scale,
1104*d83cc019SAndroid Build Coastguard Worker "reads", "rd" },
1105*d83cc019SAndroid Build Coastguard Worker { &engines->imc_writes, 6, 0, 1.0, t, engines->imc_writes_scale,
1106*d83cc019SAndroid Build Coastguard Worker "writes", "wr" },
1107*d83cc019SAndroid Build Coastguard Worker { NULL, 0, 0, 0.0, 0.0, 0.0, "unit" },
1108*d83cc019SAndroid Build Coastguard Worker { },
1109*d83cc019SAndroid Build Coastguard Worker };
1110*d83cc019SAndroid Build Coastguard Worker struct cnt_group imc_group = {
1111*d83cc019SAndroid Build Coastguard Worker .name = "imc-bandwidth",
1112*d83cc019SAndroid Build Coastguard Worker .items = imc_items,
1113*d83cc019SAndroid Build Coastguard Worker };
1114*d83cc019SAndroid Build Coastguard Worker struct cnt_group *groups[] = {
1115*d83cc019SAndroid Build Coastguard Worker &imc_group,
1116*d83cc019SAndroid Build Coastguard Worker NULL
1117*d83cc019SAndroid Build Coastguard Worker };
1118*d83cc019SAndroid Build Coastguard Worker int ret;
1119*d83cc019SAndroid Build Coastguard Worker
1120*d83cc019SAndroid Build Coastguard Worker ret = asprintf((char **)&imc_group.display_name, "IMC %s/s",
1121*d83cc019SAndroid Build Coastguard Worker engines->imc_reads_unit);
1122*d83cc019SAndroid Build Coastguard Worker assert(ret >= 0);
1123*d83cc019SAndroid Build Coastguard Worker
1124*d83cc019SAndroid Build Coastguard Worker ret = asprintf((char **)&imc_items[2].unit, "%s/s",
1125*d83cc019SAndroid Build Coastguard Worker engines->imc_reads_unit);
1126*d83cc019SAndroid Build Coastguard Worker assert(ret >= 0);
1127*d83cc019SAndroid Build Coastguard Worker
1128*d83cc019SAndroid Build Coastguard Worker print_groups(groups);
1129*d83cc019SAndroid Build Coastguard Worker
1130*d83cc019SAndroid Build Coastguard Worker free((void *)imc_group.display_name);
1131*d83cc019SAndroid Build Coastguard Worker free((void *)imc_items[2].unit);
1132*d83cc019SAndroid Build Coastguard Worker
1133*d83cc019SAndroid Build Coastguard Worker if (output_mode == INTERACTIVE) {
1134*d83cc019SAndroid Build Coastguard Worker if (lines++ < con_h)
1135*d83cc019SAndroid Build Coastguard Worker printf(" IMC reads: %s %s/s\n",
1136*d83cc019SAndroid Build Coastguard Worker imc_items[0].buf, engines->imc_reads_unit);
1137*d83cc019SAndroid Build Coastguard Worker
1138*d83cc019SAndroid Build Coastguard Worker if (lines++ < con_h)
1139*d83cc019SAndroid Build Coastguard Worker printf(" IMC writes: %s %s/s\n",
1140*d83cc019SAndroid Build Coastguard Worker imc_items[1].buf, engines->imc_writes_unit);
1141*d83cc019SAndroid Build Coastguard Worker
1142*d83cc019SAndroid Build Coastguard Worker if (lines++ < con_h)
1143*d83cc019SAndroid Build Coastguard Worker printf("\n");
1144*d83cc019SAndroid Build Coastguard Worker }
1145*d83cc019SAndroid Build Coastguard Worker
1146*d83cc019SAndroid Build Coastguard Worker return lines;
1147*d83cc019SAndroid Build Coastguard Worker }
1148*d83cc019SAndroid Build Coastguard Worker
1149*d83cc019SAndroid Build Coastguard Worker static int
print_engines_header(struct engines * engines,double t,int lines,int con_w,int con_h)1150*d83cc019SAndroid Build Coastguard Worker print_engines_header(struct engines *engines, double t,
1151*d83cc019SAndroid Build Coastguard Worker int lines, int con_w, int con_h)
1152*d83cc019SAndroid Build Coastguard Worker {
1153*d83cc019SAndroid Build Coastguard Worker for (unsigned int i = 0;
1154*d83cc019SAndroid Build Coastguard Worker i < engines->num_engines && lines < con_h;
1155*d83cc019SAndroid Build Coastguard Worker i++) {
1156*d83cc019SAndroid Build Coastguard Worker struct engine *engine = engine_ptr(engines, i);
1157*d83cc019SAndroid Build Coastguard Worker
1158*d83cc019SAndroid Build Coastguard Worker if (!engine->num_counters)
1159*d83cc019SAndroid Build Coastguard Worker continue;
1160*d83cc019SAndroid Build Coastguard Worker
1161*d83cc019SAndroid Build Coastguard Worker pops->open_struct("engines");
1162*d83cc019SAndroid Build Coastguard Worker
1163*d83cc019SAndroid Build Coastguard Worker if (output_mode == INTERACTIVE) {
1164*d83cc019SAndroid Build Coastguard Worker const char *a = " ENGINE BUSY ";
1165*d83cc019SAndroid Build Coastguard Worker const char *b = " MI_SEMA MI_WAIT";
1166*d83cc019SAndroid Build Coastguard Worker
1167*d83cc019SAndroid Build Coastguard Worker printf("\033[7m%s%*s%s\033[0m\n",
1168*d83cc019SAndroid Build Coastguard Worker a, (int)(con_w - 1 - strlen(a) - strlen(b)),
1169*d83cc019SAndroid Build Coastguard Worker " ", b);
1170*d83cc019SAndroid Build Coastguard Worker
1171*d83cc019SAndroid Build Coastguard Worker lines++;
1172*d83cc019SAndroid Build Coastguard Worker }
1173*d83cc019SAndroid Build Coastguard Worker
1174*d83cc019SAndroid Build Coastguard Worker break;
1175*d83cc019SAndroid Build Coastguard Worker }
1176*d83cc019SAndroid Build Coastguard Worker
1177*d83cc019SAndroid Build Coastguard Worker return lines;
1178*d83cc019SAndroid Build Coastguard Worker }
1179*d83cc019SAndroid Build Coastguard Worker
1180*d83cc019SAndroid Build Coastguard Worker static int
print_engine(struct engines * engines,unsigned int i,double t,int lines,int con_w,int con_h)1181*d83cc019SAndroid Build Coastguard Worker print_engine(struct engines *engines, unsigned int i, double t,
1182*d83cc019SAndroid Build Coastguard Worker int lines, int con_w, int con_h)
1183*d83cc019SAndroid Build Coastguard Worker {
1184*d83cc019SAndroid Build Coastguard Worker struct engine *engine = engine_ptr(engines, i);
1185*d83cc019SAndroid Build Coastguard Worker struct cnt_item engine_items[] = {
1186*d83cc019SAndroid Build Coastguard Worker { &engine->busy, 6, 2, 1e9, t, 100, "busy", "%" },
1187*d83cc019SAndroid Build Coastguard Worker { &engine->sema, 3, 0, 1e9, t, 100, "sema", "se" },
1188*d83cc019SAndroid Build Coastguard Worker { &engine->wait, 3, 0, 1e9, t, 100, "wait", "wa" },
1189*d83cc019SAndroid Build Coastguard Worker { NULL, 0, 0, 0.0, 0.0, 0.0, "unit", "%" },
1190*d83cc019SAndroid Build Coastguard Worker { },
1191*d83cc019SAndroid Build Coastguard Worker };
1192*d83cc019SAndroid Build Coastguard Worker struct cnt_group engine_group = {
1193*d83cc019SAndroid Build Coastguard Worker .name = engine->display_name,
1194*d83cc019SAndroid Build Coastguard Worker .display_name = engine->short_name,
1195*d83cc019SAndroid Build Coastguard Worker .items = engine_items,
1196*d83cc019SAndroid Build Coastguard Worker };
1197*d83cc019SAndroid Build Coastguard Worker struct cnt_group *groups[] = {
1198*d83cc019SAndroid Build Coastguard Worker &engine_group,
1199*d83cc019SAndroid Build Coastguard Worker NULL
1200*d83cc019SAndroid Build Coastguard Worker };
1201*d83cc019SAndroid Build Coastguard Worker
1202*d83cc019SAndroid Build Coastguard Worker if (!engine->num_counters)
1203*d83cc019SAndroid Build Coastguard Worker return lines;
1204*d83cc019SAndroid Build Coastguard Worker
1205*d83cc019SAndroid Build Coastguard Worker print_groups(groups);
1206*d83cc019SAndroid Build Coastguard Worker
1207*d83cc019SAndroid Build Coastguard Worker if (output_mode == INTERACTIVE) {
1208*d83cc019SAndroid Build Coastguard Worker unsigned int max_w = con_w - 1;
1209*d83cc019SAndroid Build Coastguard Worker unsigned int len;
1210*d83cc019SAndroid Build Coastguard Worker char buf[128];
1211*d83cc019SAndroid Build Coastguard Worker double val;
1212*d83cc019SAndroid Build Coastguard Worker
1213*d83cc019SAndroid Build Coastguard Worker len = snprintf(buf, sizeof(buf), " %s%% %s%%",
1214*d83cc019SAndroid Build Coastguard Worker engine_items[1].buf, engine_items[2].buf);
1215*d83cc019SAndroid Build Coastguard Worker
1216*d83cc019SAndroid Build Coastguard Worker len += printf("%16s %s%% ",
1217*d83cc019SAndroid Build Coastguard Worker engine->display_name, engine_items[0].buf);
1218*d83cc019SAndroid Build Coastguard Worker
1219*d83cc019SAndroid Build Coastguard Worker val = pmu_calc(&engine->busy.val, 1e9, t, 100);
1220*d83cc019SAndroid Build Coastguard Worker print_percentage_bar(val, max_w - len);
1221*d83cc019SAndroid Build Coastguard Worker
1222*d83cc019SAndroid Build Coastguard Worker printf("%s\n", buf);
1223*d83cc019SAndroid Build Coastguard Worker
1224*d83cc019SAndroid Build Coastguard Worker lines++;
1225*d83cc019SAndroid Build Coastguard Worker }
1226*d83cc019SAndroid Build Coastguard Worker
1227*d83cc019SAndroid Build Coastguard Worker return lines;
1228*d83cc019SAndroid Build Coastguard Worker }
1229*d83cc019SAndroid Build Coastguard Worker
1230*d83cc019SAndroid Build Coastguard Worker static int
print_engines_footer(struct engines * engines,double t,int lines,int con_w,int con_h)1231*d83cc019SAndroid Build Coastguard Worker print_engines_footer(struct engines *engines, double t,
1232*d83cc019SAndroid Build Coastguard Worker int lines, int con_w, int con_h)
1233*d83cc019SAndroid Build Coastguard Worker {
1234*d83cc019SAndroid Build Coastguard Worker pops->close_struct();
1235*d83cc019SAndroid Build Coastguard Worker pops->close_struct();
1236*d83cc019SAndroid Build Coastguard Worker
1237*d83cc019SAndroid Build Coastguard Worker if (output_mode == INTERACTIVE) {
1238*d83cc019SAndroid Build Coastguard Worker if (lines++ < con_h)
1239*d83cc019SAndroid Build Coastguard Worker printf("\n");
1240*d83cc019SAndroid Build Coastguard Worker }
1241*d83cc019SAndroid Build Coastguard Worker
1242*d83cc019SAndroid Build Coastguard Worker return lines;
1243*d83cc019SAndroid Build Coastguard Worker }
1244*d83cc019SAndroid Build Coastguard Worker
1245*d83cc019SAndroid Build Coastguard Worker static bool stop_top;
1246*d83cc019SAndroid Build Coastguard Worker
sigint_handler(int sig)1247*d83cc019SAndroid Build Coastguard Worker static void sigint_handler(int sig)
1248*d83cc019SAndroid Build Coastguard Worker {
1249*d83cc019SAndroid Build Coastguard Worker stop_top = true;
1250*d83cc019SAndroid Build Coastguard Worker }
1251*d83cc019SAndroid Build Coastguard Worker
main(int argc,char ** argv)1252*d83cc019SAndroid Build Coastguard Worker int main(int argc, char **argv)
1253*d83cc019SAndroid Build Coastguard Worker {
1254*d83cc019SAndroid Build Coastguard Worker unsigned int period_us = DEFAULT_PERIOD_MS * 1000;
1255*d83cc019SAndroid Build Coastguard Worker int con_w = -1, con_h = -1;
1256*d83cc019SAndroid Build Coastguard Worker char *output_path = NULL;
1257*d83cc019SAndroid Build Coastguard Worker struct engines *engines;
1258*d83cc019SAndroid Build Coastguard Worker unsigned int i;
1259*d83cc019SAndroid Build Coastguard Worker int ret, ch;
1260*d83cc019SAndroid Build Coastguard Worker
1261*d83cc019SAndroid Build Coastguard Worker /* Parse options */
1262*d83cc019SAndroid Build Coastguard Worker while ((ch = getopt(argc, argv, "o:s:Jlh")) != -1) {
1263*d83cc019SAndroid Build Coastguard Worker switch (ch) {
1264*d83cc019SAndroid Build Coastguard Worker case 'o':
1265*d83cc019SAndroid Build Coastguard Worker output_path = optarg;
1266*d83cc019SAndroid Build Coastguard Worker break;
1267*d83cc019SAndroid Build Coastguard Worker case 's':
1268*d83cc019SAndroid Build Coastguard Worker period_us = atoi(optarg) * 1000;
1269*d83cc019SAndroid Build Coastguard Worker break;
1270*d83cc019SAndroid Build Coastguard Worker case 'J':
1271*d83cc019SAndroid Build Coastguard Worker output_mode = JSON;
1272*d83cc019SAndroid Build Coastguard Worker break;
1273*d83cc019SAndroid Build Coastguard Worker case 'l':
1274*d83cc019SAndroid Build Coastguard Worker output_mode = STDOUT;
1275*d83cc019SAndroid Build Coastguard Worker break;
1276*d83cc019SAndroid Build Coastguard Worker case 'h':
1277*d83cc019SAndroid Build Coastguard Worker usage(argv[0]);
1278*d83cc019SAndroid Build Coastguard Worker exit(0);
1279*d83cc019SAndroid Build Coastguard Worker default:
1280*d83cc019SAndroid Build Coastguard Worker fprintf(stderr, "Invalid option %c!\n", (char)optopt);
1281*d83cc019SAndroid Build Coastguard Worker usage(argv[0]);
1282*d83cc019SAndroid Build Coastguard Worker exit(1);
1283*d83cc019SAndroid Build Coastguard Worker }
1284*d83cc019SAndroid Build Coastguard Worker }
1285*d83cc019SAndroid Build Coastguard Worker
1286*d83cc019SAndroid Build Coastguard Worker if (output_mode == INTERACTIVE && (output_path || isatty(1) != 1))
1287*d83cc019SAndroid Build Coastguard Worker output_mode = STDOUT;
1288*d83cc019SAndroid Build Coastguard Worker
1289*d83cc019SAndroid Build Coastguard Worker if (output_path && strcmp(output_path, "-")) {
1290*d83cc019SAndroid Build Coastguard Worker out = fopen(output_path, "w");
1291*d83cc019SAndroid Build Coastguard Worker
1292*d83cc019SAndroid Build Coastguard Worker if (!out) {
1293*d83cc019SAndroid Build Coastguard Worker fprintf(stderr, "Failed to open output file - '%s'!\n",
1294*d83cc019SAndroid Build Coastguard Worker strerror(errno));
1295*d83cc019SAndroid Build Coastguard Worker exit(1);
1296*d83cc019SAndroid Build Coastguard Worker }
1297*d83cc019SAndroid Build Coastguard Worker } else {
1298*d83cc019SAndroid Build Coastguard Worker out = stdout;
1299*d83cc019SAndroid Build Coastguard Worker }
1300*d83cc019SAndroid Build Coastguard Worker
1301*d83cc019SAndroid Build Coastguard Worker if (output_mode != INTERACTIVE) {
1302*d83cc019SAndroid Build Coastguard Worker sighandler_t sig = signal(SIGINT, sigint_handler);
1303*d83cc019SAndroid Build Coastguard Worker
1304*d83cc019SAndroid Build Coastguard Worker if (sig == SIG_ERR)
1305*d83cc019SAndroid Build Coastguard Worker fprintf(stderr, "Failed to install signal handler!\n");
1306*d83cc019SAndroid Build Coastguard Worker }
1307*d83cc019SAndroid Build Coastguard Worker
1308*d83cc019SAndroid Build Coastguard Worker switch (output_mode) {
1309*d83cc019SAndroid Build Coastguard Worker case INTERACTIVE:
1310*d83cc019SAndroid Build Coastguard Worker pops = &term_pops;
1311*d83cc019SAndroid Build Coastguard Worker break;
1312*d83cc019SAndroid Build Coastguard Worker case STDOUT:
1313*d83cc019SAndroid Build Coastguard Worker pops = &stdout_pops;
1314*d83cc019SAndroid Build Coastguard Worker break;
1315*d83cc019SAndroid Build Coastguard Worker case JSON:
1316*d83cc019SAndroid Build Coastguard Worker pops = &json_pops;
1317*d83cc019SAndroid Build Coastguard Worker break;
1318*d83cc019SAndroid Build Coastguard Worker default:
1319*d83cc019SAndroid Build Coastguard Worker assert(0);
1320*d83cc019SAndroid Build Coastguard Worker break;
1321*d83cc019SAndroid Build Coastguard Worker };
1322*d83cc019SAndroid Build Coastguard Worker
1323*d83cc019SAndroid Build Coastguard Worker engines = discover_engines();
1324*d83cc019SAndroid Build Coastguard Worker if (!engines) {
1325*d83cc019SAndroid Build Coastguard Worker fprintf(stderr,
1326*d83cc019SAndroid Build Coastguard Worker "Failed to detect engines! (%s)\n(Kernel 4.16 or newer is required for i915 PMU support.)\n",
1327*d83cc019SAndroid Build Coastguard Worker strerror(errno));
1328*d83cc019SAndroid Build Coastguard Worker return 1;
1329*d83cc019SAndroid Build Coastguard Worker }
1330*d83cc019SAndroid Build Coastguard Worker
1331*d83cc019SAndroid Build Coastguard Worker ret = pmu_init(engines);
1332*d83cc019SAndroid Build Coastguard Worker if (ret) {
1333*d83cc019SAndroid Build Coastguard Worker fprintf(stderr,
1334*d83cc019SAndroid Build Coastguard Worker "Failed to initialize PMU! (%s)\n", strerror(errno));
1335*d83cc019SAndroid Build Coastguard Worker return 1;
1336*d83cc019SAndroid Build Coastguard Worker }
1337*d83cc019SAndroid Build Coastguard Worker
1338*d83cc019SAndroid Build Coastguard Worker pmu_sample(engines);
1339*d83cc019SAndroid Build Coastguard Worker
1340*d83cc019SAndroid Build Coastguard Worker while (!stop_top) {
1341*d83cc019SAndroid Build Coastguard Worker bool consumed = false;
1342*d83cc019SAndroid Build Coastguard Worker int lines = 0;
1343*d83cc019SAndroid Build Coastguard Worker struct winsize ws;
1344*d83cc019SAndroid Build Coastguard Worker double t;
1345*d83cc019SAndroid Build Coastguard Worker
1346*d83cc019SAndroid Build Coastguard Worker /* Update terminal size. */
1347*d83cc019SAndroid Build Coastguard Worker if (output_mode != INTERACTIVE) {
1348*d83cc019SAndroid Build Coastguard Worker con_w = con_h = INT_MAX;
1349*d83cc019SAndroid Build Coastguard Worker } else if (ioctl(0, TIOCGWINSZ, &ws) != -1) {
1350*d83cc019SAndroid Build Coastguard Worker con_w = ws.ws_col;
1351*d83cc019SAndroid Build Coastguard Worker con_h = ws.ws_row;
1352*d83cc019SAndroid Build Coastguard Worker }
1353*d83cc019SAndroid Build Coastguard Worker
1354*d83cc019SAndroid Build Coastguard Worker pmu_sample(engines);
1355*d83cc019SAndroid Build Coastguard Worker t = (double)(engines->ts.cur - engines->ts.prev) / 1e9;
1356*d83cc019SAndroid Build Coastguard Worker
1357*d83cc019SAndroid Build Coastguard Worker if (stop_top)
1358*d83cc019SAndroid Build Coastguard Worker break;
1359*d83cc019SAndroid Build Coastguard Worker
1360*d83cc019SAndroid Build Coastguard Worker while (!consumed) {
1361*d83cc019SAndroid Build Coastguard Worker lines = print_header(engines, t, lines, con_w, con_h,
1362*d83cc019SAndroid Build Coastguard Worker &consumed);
1363*d83cc019SAndroid Build Coastguard Worker
1364*d83cc019SAndroid Build Coastguard Worker if (engines->imc_fd)
1365*d83cc019SAndroid Build Coastguard Worker lines = print_imc(engines, t, lines, con_w,
1366*d83cc019SAndroid Build Coastguard Worker con_h);
1367*d83cc019SAndroid Build Coastguard Worker
1368*d83cc019SAndroid Build Coastguard Worker lines = print_engines_header(engines, t, lines, con_w,
1369*d83cc019SAndroid Build Coastguard Worker con_h);
1370*d83cc019SAndroid Build Coastguard Worker
1371*d83cc019SAndroid Build Coastguard Worker for (i = 0;
1372*d83cc019SAndroid Build Coastguard Worker i < engines->num_engines && lines < con_h;
1373*d83cc019SAndroid Build Coastguard Worker i++)
1374*d83cc019SAndroid Build Coastguard Worker lines = print_engine(engines, i, t, lines,
1375*d83cc019SAndroid Build Coastguard Worker con_w, con_h);
1376*d83cc019SAndroid Build Coastguard Worker
1377*d83cc019SAndroid Build Coastguard Worker lines = print_engines_footer(engines, t, lines, con_w,
1378*d83cc019SAndroid Build Coastguard Worker con_h);
1379*d83cc019SAndroid Build Coastguard Worker }
1380*d83cc019SAndroid Build Coastguard Worker
1381*d83cc019SAndroid Build Coastguard Worker if (stop_top)
1382*d83cc019SAndroid Build Coastguard Worker break;
1383*d83cc019SAndroid Build Coastguard Worker
1384*d83cc019SAndroid Build Coastguard Worker usleep(period_us);
1385*d83cc019SAndroid Build Coastguard Worker }
1386*d83cc019SAndroid Build Coastguard Worker
1387*d83cc019SAndroid Build Coastguard Worker return 0;
1388*d83cc019SAndroid Build Coastguard Worker }
1389