11 #include <linux/bitops.h>
21 #include <linux/hw_breakpoint.h>
22 #include <linux/perf_event.h>
25 #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
33 for (i = 0; i < 64; i++) {
34 if (mask & (1ULL << i))
45 memset(hists, 0,
sizeof(*hists));
50 pthread_mutex_init(&hists->
lock,
NULL);
58 INIT_LIST_HEAD(&evsel->
node);
78 size_t size = 0, alloc_size = 0;
86 goto out_free_filename;
89 if (size == alloc_size) {
91 nbf = realloc(bf, alloc_size);
97 n =
read(fd, bf + size, BUFSIZ);
125 if (asprintf(&evsel->
name,
"%s:%s", sys, name) < 0)
154 "stalled-cycles-frontend",
155 "stalled-cycles-backend",
159 static const char *__perf_evsel__hw_name(
u64 config)
162 return perf_evsel__hw_names[
config];
164 return "unknown-hardware";
167 static int perf_evsel__add_modifiers(
struct perf_evsel *evsel,
char *
bf,
size_t size)
169 int colon = 0,
r = 0;
171 bool exclude_guest_default =
false;
173 #define MOD_PRINT(context, mod) do { \
174 if (!attr->exclude_##context) { \
175 if (!colon) colon = ++r; \
176 r += scnprintf(bf + r, size - r, "%c", mod); \
183 exclude_guest_default =
true;
190 exclude_guest_default =
true;
203 static int perf_evsel__hw_name(
struct perf_evsel *evsel,
char *bf,
size_t size)
205 int r =
scnprintf(bf, size,
"%s", __perf_evsel__hw_name(evsel->
attr.config));
206 return r + perf_evsel__add_modifiers(evsel, bf + r, size - r);
221 static const char *__perf_evsel__sw_name(
u64 config)
224 return perf_evsel__sw_names[
config];
225 return "unknown-software";
228 static int perf_evsel__sw_name(
struct perf_evsel *evsel,
char *bf,
size_t size)
230 int r =
scnprintf(bf, size,
"%s", __perf_evsel__sw_name(evsel->
attr.config));
231 return r + perf_evsel__add_modifiers(evsel, bf + r, size - r);
234 static int __perf_evsel__bp_name(
char *bf,
size_t size,
u64 addr,
u64 type)
252 static int perf_evsel__bp_name(
struct perf_evsel *evsel,
char *bf,
size_t size)
255 int r = __perf_evsel__bp_name(bf, size, attr->
bp_addr, attr->
bp_type);
256 return r + perf_evsel__add_modifiers(evsel, bf + r, size - r);
261 {
"L1-dcache",
"l1-d",
"l1d",
"L1-data", },
262 {
"L1-icache",
"l1-i",
"l1i",
"L1-instruction", },
264 {
"dTLB",
"d-tlb",
"Data-TLB", },
265 {
"iTLB",
"i-tlb",
"Instruction-TLB", },
266 {
"branch",
"branches",
"bpu",
"btb",
"bpc", },
272 {
"load",
"loads",
"read", },
273 {
"store",
"stores",
"write", },
274 {
"prefetch",
"prefetches",
"speculative-read",
"speculative-load", },
279 {
"refs",
"Reference",
"ops",
"access", },
280 {
"misses",
"miss", },
283 #define C(x) PERF_COUNT_HW_CACHE_##x
284 #define CACHE_READ (1 << C(OP_READ))
285 #define CACHE_WRITE (1 << C(OP_WRITE))
286 #define CACHE_PREFETCH (1 << C(OP_PREFETCH))
287 #define COP(x) (1 << x)
294 static unsigned long perf_evsel__hw_cache_stat[
C(
MAX)] = {
306 if (perf_evsel__hw_cache_stat[type] &
COP(op))
313 char *bf,
size_t size)
325 static int __perf_evsel__hw_cache_name(
u64 config,
char *bf,
size_t size)
328 const char *
err =
"unknown-ext-hardware-cache-type";
333 op = (config >> 8) & 0xff;
334 err =
"unknown-ext-hardware-cache-op";
338 result = (config >> 16) & 0xff;
339 err =
"unknown-ext-hardware-cache-result";
343 err =
"invalid-cache";
352 static int perf_evsel__hw_cache_name(
struct perf_evsel *evsel,
char *bf,
size_t size)
354 int ret = __perf_evsel__hw_cache_name(evsel->
attr.config, bf, size);
355 return ret + perf_evsel__add_modifiers(evsel, bf + ret, size - ret);
358 static int perf_evsel__raw_name(
struct perf_evsel *evsel,
char *bf,
size_t size)
361 return ret + perf_evsel__add_modifiers(evsel, bf + ret, size - ret);
371 switch (evsel->
attr.type) {
373 perf_evsel__raw_name(evsel, bf,
sizeof(bf));
377 perf_evsel__hw_name(evsel, bf,
sizeof(bf));
381 perf_evsel__hw_cache_name(evsel, bf,
sizeof(bf));
385 perf_evsel__sw_name(evsel, bf,
sizeof(bf));
389 scnprintf(bf,
sizeof(bf),
"%s",
"unknown tracepoint");
393 perf_evsel__bp_name(evsel, bf,
sizeof(bf));
397 scnprintf(bf,
sizeof(bf),
"unknown attr type: %d",
402 evsel->
name = strdup(bf);
404 return evsel->
name ?:
"unknown";
460 if (perf_target__has_cpu(&opts->
target))
468 perf_target__has_cpu(&opts->
target)))
489 if (perf_target__none(&opts->
target) &&
490 (!opts->
group || evsel == first)) {
501 for (cpu = 0; cpu <
ncpus; cpu++) {
502 for (thread = 0; thread < nthreads; thread++) {
503 FD(evsel, cpu, thread) = -1;
516 for (cpu = 0; cpu <
ncpus; cpu++) {
517 for (thread = 0; thread < nthreads; thread++) {
518 int fd =
FD(evsel, cpu, thread),
535 evsel->
id =
zalloc(ncpus * nthreads *
sizeof(
u64));
570 for (cpu = 0; cpu <
ncpus; cpu++)
571 for (thread = 0; thread < nthreads; ++
thread) {
572 close(
FD(evsel, cpu, thread));
573 FD(evsel, cpu, thread) = -1;
600 size_t nv = scale ? 3 : 1;
602 if (
FD(evsel, cpu, thread) < 0)
608 if (
readn(
FD(evsel, cpu, thread), &count, nv *
sizeof(
u64)) < 0)
614 else if (count.
run < count.
ena)
617 count.
ena = count.
run = 0;
624 int ncpus,
int nthreads,
bool scale)
626 size_t nv = scale ? 3 : 1;
632 for (cpu = 0; cpu <
ncpus; cpu++) {
633 for (thread = 0; thread < nthreads; thread++) {
634 if (
FD(evsel, cpu, thread) < 0)
637 if (
readn(
FD(evsel, cpu, thread),
649 evsel->
counts->scaled = 0;
651 if (aggr->
run == 0) {
652 evsel->
counts->scaled = -1;
657 if (aggr->
run < aggr->
ena) {
658 evsel->
counts->scaled = 1;
662 aggr->
ena = aggr->
run = 0;
681 fd =
FD(leader, cpu, thread);
691 unsigned long flags = 0;
700 pid = evsel->
cgrp->fd;
703 for (cpu = 0; cpu < cpus->
nr; cpu++) {
705 for (thread = 0; thread < threads->
nr; thread++) {
711 group_fd = get_group_fd(evsel, cpu, thread);
717 if (
FD(evsel, cpu, thread) < 0) {
728 while (--thread >= 0) {
729 close(
FD(evsel, cpu, thread));
730 FD(evsel, cpu, thread) = -1;
732 thread = threads->
nr;
733 }
while (--cpu >= 0);
758 } empty_thread_map = {
768 cpus = &empty_cpu_map.map;
772 threads = &empty_thread_map.map;
774 return __perf_evsel__open(evsel, cpus, threads);
780 return __perf_evsel__open(evsel, cpus, &empty_thread_map.map);
786 return __perf_evsel__open(evsel, &empty_cpu_map.map, threads);
789 static int perf_evsel__parse_id_sample(
const struct perf_evsel *evsel,
793 u64 type = evsel->
attr.sample_type;
794 const u64 *array =
event->sample.array;
798 array += ((
event->header.size -
799 sizeof(
event->header)) /
sizeof(
u64)) - 1;
805 u.val64 = bswap_64(
u.val64);
806 u.val32[0] = bswap_32(
u.val32[0]);
809 sample->
cpu =
u.val32[0];
824 sample->
time = *array;
832 u.val64 = bswap_64(
u.val64);
833 u.val32[0] = bswap_32(
u.val32[0]);
834 u.val32[1] = bswap_32(
u.val32[1]);
837 sample->
pid =
u.val32[0];
838 sample->
tid =
u.val32[1];
844 static bool sample_overlap(
const union perf_event *event,
849 if (offset + size > base + event->
header.size)
858 u64 type = evsel->
attr.sample_type;
859 u64 regs_user = evsel->
attr.sample_regs_user;
869 memset(data, 0,
sizeof(*data));
875 if (!evsel->
attr.sample_id_all)
877 return perf_evsel__parse_id_sample(evsel, event, data);
880 array =
event->sample.array;
886 data->
ip =
event->ip.ip;
890 if (type & PERF_SAMPLE_TID) {
904 if (type & PERF_SAMPLE_TIME) {
916 if (type & PERF_SAMPLE_ID) {
921 if (type & PERF_SAMPLE_STREAM_ID) {
926 if (type & PERF_SAMPLE_CPU) {
945 fprintf(stderr,
"PERF_SAMPLE_READ is unsupported for now\n");
950 if (sample_overlap(event, array,
sizeof(data->
callchain->nr)))
955 if (sample_overlap(event, array, data->
callchain->nr))
966 "Endianness of raw data not corrected!\n")) {
973 if (sample_overlap(event, array,
sizeof(
u32)))
977 pdata = (
void *) array +
sizeof(
u32);
979 if (sample_overlap(event, pdata, data->
raw_size))
984 array = (
void *)array + data->
raw_size +
sizeof(
u32);
1004 array += hweight_long(regs_user);
1009 u64 size = *array++;
1011 data->
user_stack.offset = ((
char *)(array - 1)
1018 array += size /
sizeof(*array);
1038 array =
event->sample.array;
1041 event->ip.ip = sample->
ip;
1045 if (type & PERF_SAMPLE_TID) {
1061 if (type & PERF_SAMPLE_TIME) {
1062 *array = sample->
time;
1067 *array = sample->
addr;
1071 if (type & PERF_SAMPLE_ID) {
1072 *array = sample->
id;
1076 if (type & PERF_SAMPLE_STREAM_ID) {
1081 if (type & PERF_SAMPLE_CPU) {
1138 switch (field->
size) {
1142 value = *(
u16 *)ptr;
1145 value = *(
u32 *)ptr;
1148 value = *(
u64 *)ptr;
1157 switch (field->
size) {
1159 return bswap_16(value);
1161 return bswap_32(value);
1163 return bswap_64(value);