1 #include <stdint.h>
2 #include <fcntl.h>
3 #include <unistd.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <errno.h>
7 #include <sys/sysinfo.h>
8 
9 #include "igt_perf.h"
10 
i915_type_id(void)11 uint64_t i915_type_id(void)
12 {
13 	char buf[64];
14 	ssize_t ret;
15 	int fd;
16 
17 	fd = open("/sys/bus/event_source/devices/i915/type", O_RDONLY);
18 	if (fd < 0)
19 		return 0;
20 
21 	ret = read(fd, buf, sizeof(buf) - 1);
22 	close(fd);
23 	if (ret < 1)
24 		return 0;
25 
26 	buf[ret] = '\0';
27 
28 	return strtoull(buf, NULL, 0);
29 }
30 
31 static int
_perf_open(uint64_t type,uint64_t config,int group,uint64_t format)32 _perf_open(uint64_t type, uint64_t config, int group, uint64_t format)
33 {
34 	struct perf_event_attr attr = { };
35 	int nr_cpus = get_nprocs_conf();
36 	int cpu = 0, ret;
37 
38 	attr.type = type;
39 	if (attr.type == 0)
40 		return -ENOENT;
41 
42 	if (group >= 0)
43 		format &= ~PERF_FORMAT_GROUP;
44 
45 	attr.read_format = format;
46 	attr.config = config;
47 
48 	do {
49 		ret = perf_event_open(&attr, -1, cpu++, group, 0);
50 	} while ((ret < 0 && errno == EINVAL) && (cpu < nr_cpus));
51 
52 	return ret;
53 }
54 
perf_i915_open(uint64_t config)55 int perf_i915_open(uint64_t config)
56 {
57 	return _perf_open(i915_type_id(), config, -1,
58 			  PERF_FORMAT_TOTAL_TIME_ENABLED);
59 }
60 
perf_i915_open_group(uint64_t config,int group)61 int perf_i915_open_group(uint64_t config, int group)
62 {
63 	return _perf_open(i915_type_id(), config, group,
64 			  PERF_FORMAT_TOTAL_TIME_ENABLED | PERF_FORMAT_GROUP);
65 }
66 
igt_perf_open(uint64_t type,uint64_t config)67 int igt_perf_open(uint64_t type, uint64_t config)
68 {
69 	return _perf_open(type, config, -1,
70 			  PERF_FORMAT_TOTAL_TIME_ENABLED);
71 }
72 
igt_perf_open_group(uint64_t type,uint64_t config,int group)73 int igt_perf_open_group(uint64_t type, uint64_t config, int group)
74 {
75 	return _perf_open(type, config, group,
76 			  PERF_FORMAT_TOTAL_TIME_ENABLED | PERF_FORMAT_GROUP);
77 }
78