Blame src/libpfm4/perf_examples/perf_util.c

Packit 577717
/*
Packit 577717
 * perf_util.c - helper functions for perf_events
Packit 577717
 *
Packit 577717
 * Copyright (c) 2009 Google, Inc
Packit 577717
 * Contributed by Stephane Eranian <eranian@gmail.com>
Packit 577717
 *
Packit 577717
 * Permission is hereby granted, free of charge, to any person obtaining a copy
Packit 577717
 * of this software and associated documentation files (the "Software"), to deal
Packit 577717
 * in the Software without restriction, including without limitation the rights
Packit 577717
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
Packit 577717
 * of the Software, and to permit persons to whom the Software is furnished to do so,
Packit 577717
 * subject to the following conditions:
Packit 577717
 *
Packit 577717
 * The above copyright notice and this permission notice shall be included in all
Packit 577717
 * copies or substantial portions of the Software.
Packit 577717
 *
Packit 577717
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
Packit 577717
 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
Packit 577717
 * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
Packit 577717
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
Packit 577717
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
Packit 577717
 * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Packit 577717
 */
Packit 577717
#include <sys/types.h>
Packit 577717
#include <inttypes.h>
Packit 577717
#include <stdio.h>
Packit 577717
#include <stdlib.h>
Packit 577717
#include <string.h>
Packit 577717
#include <unistd.h>
Packit 577717
#include <err.h>
Packit 577717
Packit 577717
#include <perfmon/pfmlib_perf_event.h>
Packit 577717
#include "perf_util.h"
Packit 577717
Packit 577717
/* the **fd parameter must point to a null pointer on the first call
Packit 577717
 * max_fds and num_fds must both point to a zero value on the first call
Packit 577717
 * The return value is success (0) vs. failure (non-zero)
Packit 577717
 */
Packit 577717
int
Packit 577717
perf_setup_argv_events(const char **argv, perf_event_desc_t **fds, int *num_fds)
Packit 577717
{
Packit 577717
	perf_event_desc_t *fd;
Packit 577717
	pfm_perf_encode_arg_t arg;
Packit 577717
	int new_max, ret, num, max_fds;
Packit 577717
	int group_leader;
Packit 577717
Packit 577717
	if (!(argv && fds && num_fds))
Packit 577717
		return -1;
Packit 577717
Packit 577717
	fd = *fds;
Packit 577717
	if (fd) {
Packit 577717
		max_fds = fd[0].max_fds;
Packit 577717
		if (max_fds < 2)
Packit 577717
			return -1;
Packit 577717
		num = *num_fds;
Packit 577717
	} else {
Packit 577717
		max_fds = num = 0; /* bootstrap */
Packit 577717
	}
Packit 577717
	group_leader = num;
Packit 577717
Packit 577717
	while(*argv) {
Packit 577717
		if (num == max_fds) {
Packit 577717
			if (max_fds == 0)
Packit 577717
				new_max = 2;
Packit 577717
			else
Packit 577717
				new_max = max_fds << 1;
Packit 577717
Packit 577717
			if (new_max < max_fds) {
Packit 577717
				warn("too many entries");
Packit 577717
				goto error;
Packit 577717
			}
Packit 577717
			fd = realloc(fd, new_max * sizeof(*fd));
Packit 577717
			if (!fd) {
Packit 577717
				warn("cannot allocate memory");
Packit 577717
				goto error;
Packit 577717
			}
Packit 577717
			/* reset newly allocated chunk */
Packit 577717
			memset(fd + max_fds, 0, (new_max - max_fds) * sizeof(*fd));
Packit 577717
			max_fds = new_max;
Packit 577717
Packit 577717
			/* update max size */
Packit 577717
			fd[0].max_fds = max_fds;
Packit 577717
		}
Packit 577717
		/* ABI compatibility, set before calling libpfm */
Packit 577717
		fd[num].hw.size = sizeof(fd[num].hw);
Packit 577717
Packit 577717
		memset(&arg, 0, sizeof(arg));
Packit 577717
		arg.attr = &fd[num].hw;
Packit 577717
		arg.fstr = &fd[num].fstr; /* fd[].fstr is NULL */
Packit 577717
Packit 577717
		ret = pfm_get_os_event_encoding(*argv, PFM_PLM0|PFM_PLM3, PFM_OS_PERF_EVENT_EXT, &arg;;
Packit 577717
		if (ret != PFM_SUCCESS) {
Packit 577717
			warnx("event %s: %s", *argv, pfm_strerror(ret));
Packit 577717
			goto error;
Packit 577717
		}
Packit 577717
Packit 577717
		fd[num].name = strdup(*argv);
Packit 577717
		fd[num].group_leader = group_leader;
Packit 577717
		fd[num].idx = arg.idx;
Packit 577717
		fd[num].cpu = arg.cpu;
Packit 577717
Packit 577717
		num++;
Packit 577717
		argv++;
Packit 577717
	}
Packit 577717
	*num_fds = num;
Packit 577717
	*fds = fd;
Packit 577717
	return 0;
Packit 577717
error:
Packit 577717
	perf_free_fds(fd, num);
Packit 577717
	return -1;
Packit 577717
}
Packit 577717
Packit 577717
int
Packit 577717
perf_setup_list_events(const char *ev, perf_event_desc_t **fd, int *num_fds)
Packit 577717
{
Packit 577717
	const char **argv;
Packit 577717
	char *p, *q, *events;
Packit 577717
	int i, ret, num = 0;
Packit 577717
Packit 577717
	if (!(ev && fd && num_fds))
Packit 577717
		return -1;
Packit 577717
Packit 577717
	events = strdup(ev);
Packit 577717
	if (!events)
Packit 577717
		return -1;
Packit 577717
Packit 577717
	q = events;
Packit 577717
	while((p = strchr(q, ','))) {
Packit 577717
		num++;
Packit 577717
		q = p + 1;
Packit 577717
	}
Packit 577717
	num++;
Packit 577717
	num++; /* terminator */
Packit 577717
Packit 577717
	argv = malloc(num * sizeof(char *));
Packit 577717
	if (!argv) {
Packit 577717
		free(events);
Packit 577717
		return -1;
Packit 577717
	}
Packit 577717
Packit 577717
	i = 0; q = events;
Packit 577717
	while((p = strchr(q, ','))) {
Packit 577717
		*p = '\0';
Packit 577717
		argv[i++] = q;
Packit 577717
		q = p + 1;
Packit 577717
	}
Packit 577717
	argv[i++] = q;
Packit 577717
	argv[i] = NULL;
Packit 577717
Packit 577717
	ret = perf_setup_argv_events(argv, fd, num_fds);
Packit 577717
	free(argv);
Packit 577717
	free(events); /* strdup in perf_setup_argv_events() */
Packit 577717
	return ret;
Packit 577717
}
Packit 577717
Packit 577717
void
Packit 577717
perf_free_fds(perf_event_desc_t *fds, int num_fds)
Packit 577717
{
Packit 577717
	int i;
Packit 577717
Packit 577717
	for (i = 0 ; i < num_fds; i++) {
Packit 577717
		free(fds[i].name);
Packit 577717
		free(fds[i].fstr);
Packit 577717
	}
Packit 577717
	free(fds);
Packit 577717
}
Packit 577717
Packit 577717
int
Packit 577717
perf_get_group_nevents(perf_event_desc_t *fds, int num, int idx)
Packit 577717
{
Packit 577717
	int leader;
Packit 577717
	int i;
Packit 577717
Packit 577717
	if (idx < 0 || idx >= num)
Packit 577717
		return 0;
Packit 577717
Packit 577717
	leader = fds[idx].group_leader;
Packit 577717
Packit 577717
	for (i = leader + 1; i < num; i++) {
Packit 577717
		if (fds[i].group_leader != leader) {
Packit 577717
			/* This is a new group leader, so the previous
Packit 577717
			 * event was the final event of the preceding
Packit 577717
			 * group.
Packit 577717
			 */
Packit 577717
			return i - leader;
Packit 577717
		}
Packit 577717
	}
Packit 577717
	return i - leader;
Packit 577717
}
Packit 577717
Packit 577717
int
Packit 577717
perf_read_buffer(perf_event_desc_t *hw, void *buf, size_t sz)
Packit 577717
{
Packit 577717
	struct perf_event_mmap_page *hdr = hw->buf;
Packit 577717
	size_t pgmsk = hw->pgmsk;
Packit 577717
	void *data;
Packit 577717
	unsigned long tail;
Packit 577717
	size_t avail_sz, m, c;
Packit 577717
	
Packit 577717
	/*
Packit 577717
	 * data points to beginning of buffer payload
Packit 577717
	 */
Packit 577717
	data = ((void *)hdr)+sysconf(_SC_PAGESIZE);
Packit 577717
Packit 577717
	/*
Packit 577717
	 * position of tail within the buffer payload
Packit 577717
	 */
Packit 577717
	tail = hdr->data_tail & pgmsk;
Packit 577717
Packit 577717
	/*
Packit 577717
	 * size of what is available
Packit 577717
	 *
Packit 577717
	 * data_head, data_tail never wrap around
Packit 577717
	 */
Packit 577717
	avail_sz = hdr->data_head - hdr->data_tail;
Packit 577717
	if (sz > avail_sz)
Packit 577717
		return -1;
Packit 577717
Packit 577717
	/*
Packit 577717
	 * sz <= avail_sz, we can satisfy the request
Packit 577717
	 */
Packit 577717
Packit 577717
	/*
Packit 577717
	 * c = size till end of buffer
Packit 577717
	 *
Packit 577717
	 * buffer payload size is necessarily
Packit 577717
	 * a power of two, so we can do:
Packit 577717
	 */
Packit 577717
	c = pgmsk + 1 -  tail;
Packit 577717
Packit 577717
	/*
Packit 577717
	 * min with requested size
Packit 577717
	 */
Packit 577717
	m = c < sz ? c : sz;
Packit 577717
Packit 577717
	/* copy beginning */
Packit 577717
	memcpy(buf, data+tail, m);
Packit 577717
Packit 577717
	/*
Packit 577717
	 * copy wrapped around leftover
Packit 577717
	 */
Packit 577717
	if (sz > m)
Packit 577717
		memcpy(buf+m, data, sz - m);
Packit 577717
Packit 577717
	//printf("\nhead=%lx tail=%lx new_tail=%lx sz=%zu\n", hdr->data_head, hdr->data_tail, hdr->data_tail+sz, sz);
Packit 577717
	hdr->data_tail += sz;
Packit 577717
Packit 577717
	return 0;
Packit 577717
}
Packit 577717
Packit 577717
void
Packit 577717
perf_skip_buffer(perf_event_desc_t *hw, size_t sz)
Packit 577717
{
Packit 577717
	struct perf_event_mmap_page *hdr = hw->buf;
Packit 577717
Packit 577717
	if ((hdr->data_tail + sz) > hdr->data_head)
Packit 577717
		sz = hdr->data_head - hdr->data_tail;
Packit 577717
Packit 577717
	hdr->data_tail += sz;
Packit 577717
}
Packit 577717
Packit 577717
static size_t
Packit 577717
__perf_handle_raw(perf_event_desc_t *hw)
Packit 577717
{
Packit 577717
	size_t sz = 0;
Packit 577717
	uint32_t raw_sz, i;
Packit 577717
	char *buf;
Packit 577717
	int ret;
Packit 577717
Packit 577717
	ret = perf_read_buffer_32(hw, &raw_sz);
Packit 577717
	if (ret) {
Packit 577717
		warnx("cannot read raw size");
Packit 577717
		return -1;
Packit 577717
	}
Packit 577717
Packit 577717
	sz += sizeof(raw_sz);
Packit 577717
Packit 577717
	printf("\n\tRAWSZ:%u\n", raw_sz);
Packit 577717
Packit 577717
	buf = malloc(raw_sz);
Packit 577717
	if (!buf) {
Packit 577717
		warn("cannot allocate raw buffer");
Packit 577717
		return -1;
Packit 577717
	}
Packit 577717
Packit 577717
Packit 577717
	ret = perf_read_buffer(hw, buf, raw_sz);
Packit 577717
	if (ret) {
Packit 577717
		warnx("cannot read raw data");
Packit 577717
		free(buf);
Packit 577717
		return -1;
Packit 577717
	}
Packit 577717
Packit 577717
	if (raw_sz)
Packit 577717
		putchar('\t');
Packit 577717
Packit 577717
	for(i=0; i < raw_sz; i++) {
Packit 577717
		printf("0x%02x ", buf[i] & 0xff );
Packit 577717
		if (((i+1) % 16)  == 0)
Packit 577717
			printf("\n\t");
Packit 577717
	}
Packit 577717
	if (raw_sz)
Packit 577717
		putchar('\n');
Packit 577717
Packit 577717
	free(buf);
Packit 577717
Packit 577717
	return sz + raw_sz;
Packit 577717
}
Packit 577717
Packit 577717
static int
Packit 577717
perf_display_branch_stack(perf_event_desc_t *desc, FILE *fp)
Packit 577717
{
Packit 577717
	struct perf_branch_entry b;
Packit 577717
	uint64_t nr, n;
Packit 577717
	int ret;
Packit 577717
Packit 577717
	ret = perf_read_buffer(desc, &n, sizeof(n));
Packit 577717
	if (ret)
Packit 577717
		errx(1, "cannot read branch stack nr");
Packit 577717
Packit 577717
	fprintf(fp, "\n\tBRANCH_STACK:%"PRIu64"\n", n);
Packit 577717
	nr = n;
Packit 577717
	/*
Packit 577717
	 * from most recent to least recent take branch
Packit 577717
	 */
Packit 577717
	while (nr--) {
Packit 577717
		ret = perf_read_buffer(desc, &b, sizeof(b));
Packit 577717
		if (ret)
Packit 577717
			errx(1, "cannot read branch stack entry");
Packit 577717
Packit 577717
		fprintf(fp, "\tFROM:0x%016"PRIx64" TO:0x%016"PRIx64" MISPRED:%c PRED:%c IN_TX:%c ABORT:%c CYCLES:%d type:%d\n",
Packit 577717
			b.from,
Packit 577717
			b.to,
Packit 577717
			!(b.mispred || b.predicted) ? '-': (b.mispred ? 'Y' :'N'),
Packit 577717
			!(b.mispred || b.predicted) ? '-': (b.predicted? 'Y' :'N'),
Packit 577717
			(b.in_tx? 'Y' :'N'),
Packit 577717
			(b.abort? 'Y' :'N'),
Packit 577717
			b.type,
Packit 577717
			b.cycles);
Packit 577717
	}
Packit 577717
	return (int)(n * sizeof(b) + sizeof(n));
Packit 577717
}
Packit 577717
Packit 577717
static int
Packit 577717
perf_display_regs_user(perf_event_desc_t *hw, FILE *fp)
Packit 577717
{
Packit 577717
	errx(1, "display regs_user not implemented yet\n");
Packit 577717
	return 0;
Packit 577717
}
Packit 577717
Packit 577717
static int
Packit 577717
perf_display_regs_intr(perf_event_desc_t *hw, FILE *fp)
Packit 577717
{
Packit 577717
	errx(1, "display regs_intr not implemented yet\n");
Packit 577717
	return 0;
Packit 577717
}
Packit 577717
Packit 577717
static int
Packit 577717
perf_display_stack_user(perf_event_desc_t *hw, FILE *fp)
Packit 577717
{
Packit 577717
	uint64_t nr;
Packit 577717
	char buf[512];
Packit 577717
	size_t sz;
Packit 577717
	int ret;
Packit 577717
Packit 577717
	ret = perf_read_buffer(hw, &nr, sizeof(nr));
Packit 577717
	if (ret)
Packit 577717
		errx(1, "cannot user stack size");
Packit 577717
Packit 577717
	fprintf(fp, "USER_STACK: SZ:%"PRIu64"\n", nr);
Packit 577717
Packit 577717
	/* consume content */
Packit 577717
	while (nr) {
Packit 577717
		sz = nr;
Packit 577717
		if (sz > sizeof(buf))
Packit 577717
			sz = sizeof(buf);
Packit 577717
Packit 577717
		ret = perf_read_buffer(hw, buf, sz);
Packit 577717
		if (ret)
Packit 577717
			errx(1, "cannot user stack content");
Packit 577717
		nr -= sz;
Packit 577717
	}
Packit 577717
Packit 577717
	return 0;
Packit 577717
}
Packit 577717
Packit 577717
int
Packit 577717
perf_display_sample(perf_event_desc_t *fds, int num_fds, int idx, struct perf_event_header *ehdr, FILE *fp)
Packit 577717
{
Packit 577717
	perf_event_desc_t *hw;
Packit 577717
	struct { uint32_t pid, tid; } pid;
Packit 577717
	struct { uint64_t value, id; } grp;
Packit 577717
	uint64_t time_enabled, time_running;
Packit 577717
	size_t sz;
Packit 577717
	uint64_t type, fmt;
Packit 577717
	uint64_t val64;
Packit 577717
	const char *str;
Packit 577717
	int ret, e;
Packit 577717
Packit 577717
	if (!fds || !fp || !ehdr  || num_fds < 0 || idx < 0 ||  idx >= num_fds)
Packit 577717
		return -1;
Packit 577717
Packit 577717
	sz = ehdr->size - sizeof(*ehdr);
Packit 577717
Packit 577717
	hw = fds+idx;
Packit 577717
Packit 577717
	type = hw->hw.sample_type;
Packit 577717
	fmt  = hw->hw.read_format;
Packit 577717
Packit 577717
	if (type & PERF_SAMPLE_IDENTIFIER) {
Packit 577717
		ret = perf_read_buffer_64(hw, &val64);
Packit 577717
		if (ret) {
Packit 577717
			warnx("cannot read IP");
Packit 577717
			return -1;
Packit 577717
		}
Packit 577717
		fprintf(fp, "ID:%"PRIu64" ", val64);
Packit 577717
		sz -= sizeof(val64);
Packit 577717
	}
Packit 577717
	/*
Packit 577717
	 * the sample_type information is laid down
Packit 577717
	 * based on the PERF_RECORD_SAMPLE format specified
Packit 577717
	 * in the perf_event.h header file.
Packit 577717
	 * That order is different from the enum perf_event_sample_format
Packit 577717
	 */
Packit 577717
	if (type & PERF_SAMPLE_IP) {
Packit 577717
		const char *xtra = " ";
Packit 577717
		ret = perf_read_buffer_64(hw, &val64);
Packit 577717
		if (ret) {
Packit 577717
			warnx("cannot read IP");
Packit 577717
			return -1;
Packit 577717
		}
Packit 577717
Packit 577717
		/*
Packit 577717
		 * MISC_EXACT_IP indicates that kernel is returning
Packit 577717
		 * th  IIP of an instruction which caused the event, i.e.,
Packit 577717
		 * no skid
Packit 577717
		 */
Packit 577717
		if (hw->hw.precise_ip && (ehdr->misc & PERF_RECORD_MISC_EXACT_IP))
Packit 577717
			xtra = " (exact) ";
Packit 577717
Packit 577717
		fprintf(fp, "IIP:%#016"PRIx64"%s", val64, xtra);
Packit 577717
		sz -= sizeof(val64);
Packit 577717
	}
Packit 577717
Packit 577717
	if (type & PERF_SAMPLE_TID) {
Packit 577717
		ret = perf_read_buffer(hw, &pid, sizeof(pid));
Packit 577717
		if (ret) {
Packit 577717
			warnx( "cannot read PID");
Packit 577717
			return -1;
Packit 577717
		}
Packit 577717
Packit 577717
		fprintf(fp, "PID:%d TID:%d ", pid.pid, pid.tid);
Packit 577717
		sz -= sizeof(pid);
Packit 577717
	}
Packit 577717
Packit 577717
	if (type & PERF_SAMPLE_TIME) {
Packit 577717
		ret = perf_read_buffer_64(hw, &val64);
Packit 577717
		if (ret) {
Packit 577717
			warnx( "cannot read time");
Packit 577717
			return -1;
Packit 577717
		}
Packit 577717
Packit 577717
		fprintf(fp, "TIME:%'"PRIu64" ", val64);
Packit 577717
		sz -= sizeof(val64);
Packit 577717
	}
Packit 577717
Packit 577717
	if (type & PERF_SAMPLE_ADDR) {
Packit 577717
		ret = perf_read_buffer_64(hw, &val64);
Packit 577717
		if (ret) {
Packit 577717
			warnx( "cannot read addr");
Packit 577717
			return -1;
Packit 577717
		}
Packit 577717
Packit 577717
		fprintf(fp, "ADDR:%#016"PRIx64" ", val64);
Packit 577717
		sz -= sizeof(val64);
Packit 577717
	}
Packit 577717
Packit 577717
	if (type & PERF_SAMPLE_ID) {
Packit 577717
		ret = perf_read_buffer_64(hw, &val64);
Packit 577717
		if (ret) {
Packit 577717
			warnx( "cannot read id");
Packit 577717
			return -1;
Packit 577717
		}
Packit 577717
Packit 577717
		fprintf(fp, "ID:%"PRIu64" ", val64);
Packit 577717
		sz -= sizeof(val64);
Packit 577717
	}
Packit 577717
Packit 577717
	if (type & PERF_SAMPLE_STREAM_ID) {
Packit 577717
		ret = perf_read_buffer_64(hw, &val64);
Packit 577717
		if (ret) {
Packit 577717
			warnx( "cannot read stream_id");
Packit 577717
			return -1;
Packit 577717
		}
Packit 577717
		fprintf(fp, "STREAM_ID:%"PRIu64" ", val64);
Packit 577717
		sz -= sizeof(val64);
Packit 577717
	}
Packit 577717
Packit 577717
	if (type & PERF_SAMPLE_CPU) {
Packit 577717
		struct { uint32_t cpu, reserved; } cpu;
Packit 577717
		ret = perf_read_buffer(hw, &cpu, sizeof(cpu));
Packit 577717
		if (ret) {
Packit 577717
			warnx( "cannot read cpu");
Packit 577717
			return -1;
Packit 577717
		}
Packit 577717
		fprintf(fp, "CPU:%u ", cpu.cpu);
Packit 577717
		sz -= sizeof(cpu);
Packit 577717
	}
Packit 577717
Packit 577717
	if (type & PERF_SAMPLE_PERIOD) {
Packit 577717
		ret = perf_read_buffer_64(hw, &val64);
Packit 577717
		if (ret) {
Packit 577717
			warnx( "cannot read period");
Packit 577717
			return -1;
Packit 577717
		}
Packit 577717
		fprintf(fp, "PERIOD:%'"PRIu64" ", val64);
Packit 577717
		sz -= sizeof(val64);
Packit 577717
	}
Packit 577717
Packit 577717
	/* struct read_format {
Packit 577717
	 * 	{ u64		value;
Packit 577717
	 * 	  { u64		time_enabled; } && PERF_FORMAT_ENABLED
Packit 577717
	 * 	  { u64		time_running; } && PERF_FORMAT_RUNNING
Packit 577717
	 * 	  { u64		id;           } && PERF_FORMAT_ID
Packit 577717
	 * 	} && !PERF_FORMAT_GROUP
Packit 577717
	 *
Packit 577717
	 * 	{ u64		nr;
Packit 577717
	 * 	  { u64		time_enabled; } && PERF_FORMAT_ENABLED
Packit 577717
	 * 	  { u64		time_running; } && PERF_FORMAT_RUNNING
Packit 577717
	 * 	  { u64		value;
Packit 577717
	 * 	    { u64	id;           } && PERF_FORMAT_ID
Packit 577717
	 * 	  }		cntr[nr];
Packit 577717
	 * 	} && PERF_FORMAT_GROUP
Packit 577717
	 * };
Packit 577717
	 */
Packit 577717
	if (type & PERF_SAMPLE_READ) {
Packit 577717
		uint64_t values[3];
Packit 577717
		uint64_t nr;
Packit 577717
Packit 577717
		if (fmt & PERF_FORMAT_GROUP) {
Packit 577717
			ret = perf_read_buffer_64(hw, &nr);
Packit 577717
			if (ret) {
Packit 577717
				warnx( "cannot read nr");
Packit 577717
				return -1;
Packit 577717
			}
Packit 577717
Packit 577717
			sz -= sizeof(nr);
Packit 577717
Packit 577717
			time_enabled = time_running = 1;
Packit 577717
Packit 577717
			if (fmt & PERF_FORMAT_TOTAL_TIME_ENABLED) {
Packit 577717
				ret = perf_read_buffer_64(hw, &time_enabled);
Packit 577717
				if (ret) {
Packit 577717
					warnx( "cannot read timing info");
Packit 577717
					return -1;
Packit 577717
				}
Packit 577717
				sz -= sizeof(time_enabled);
Packit 577717
			}
Packit 577717
Packit 577717
			if (fmt & PERF_FORMAT_TOTAL_TIME_RUNNING) {
Packit 577717
				ret = perf_read_buffer_64(hw, &time_running);
Packit 577717
				if (ret) {
Packit 577717
					warnx( "cannot read timing info");
Packit 577717
					return -1;
Packit 577717
				}
Packit 577717
				sz -= sizeof(time_running);
Packit 577717
			}
Packit 577717
Packit 577717
			fprintf(fp, "ENA=%'"PRIu64" RUN=%'"PRIu64" NR=%"PRIu64"\n", time_enabled, time_running, nr);
Packit 577717
Packit 577717
			values[1] = time_enabled;
Packit 577717
			values[2] = time_running;
Packit 577717
			while(nr--) {
Packit 577717
				grp.id = -1;
Packit 577717
				ret = perf_read_buffer_64(hw, &grp.value);
Packit 577717
				if (ret) {
Packit 577717
					warnx( "cannot read group value");
Packit 577717
					return -1;
Packit 577717
				}
Packit 577717
				sz -= sizeof(grp.value);
Packit 577717
Packit 577717
				if (fmt & PERF_FORMAT_ID) {
Packit 577717
					ret = perf_read_buffer_64(hw, &grp.id);
Packit 577717
					if (ret) {
Packit 577717
						warnx( "cannot read leader id");
Packit 577717
						return -1;
Packit 577717
					}
Packit 577717
					sz -= sizeof(grp.id);
Packit 577717
				}
Packit 577717
Packit 577717
				e = perf_id2event(fds, num_fds, grp.id);
Packit 577717
				if (e == -1)
Packit 577717
					str = "unknown sample event";
Packit 577717
				else
Packit 577717
					str = fds[e].name;
Packit 577717
Packit 577717
				values[0] = grp.value;
Packit 577717
				grp.value = perf_scale(values);
Packit 577717
Packit 577717
				fprintf(fp, "\t%'"PRIu64" %s (%"PRIu64"%s)\n",
Packit 577717
					grp.value, str,
Packit 577717
					grp.id,
Packit 577717
					time_running != time_enabled ? ", scaled":"");
Packit 577717
Packit 577717
			}
Packit 577717
		} else {
Packit 577717
			time_enabled = time_running = 0;
Packit 577717
			/*
Packit 577717
			 * this program does not use FORMAT_GROUP when there is only one event
Packit 577717
			 */
Packit 577717
			ret = perf_read_buffer_64(hw, &val64);
Packit 577717
			if (ret) {
Packit 577717
				warnx( "cannot read value");
Packit 577717
				return -1;
Packit 577717
			}
Packit 577717
			sz -= sizeof(val64);
Packit 577717
Packit 577717
			if (fmt & PERF_FORMAT_TOTAL_TIME_ENABLED) {
Packit 577717
				ret = perf_read_buffer_64(hw, &time_enabled);
Packit 577717
				if (ret) {
Packit 577717
					warnx( "cannot read timing info");
Packit 577717
					return -1;
Packit 577717
				}
Packit 577717
				sz -= sizeof(time_enabled);
Packit 577717
			}
Packit 577717
Packit 577717
			if (fmt & PERF_FORMAT_TOTAL_TIME_RUNNING) {
Packit 577717
				ret = perf_read_buffer_64(hw, &time_running);
Packit 577717
				if (ret) {
Packit 577717
					warnx( "cannot read timing info");
Packit 577717
					return -1;
Packit 577717
				}
Packit 577717
				sz -= sizeof(time_running);
Packit 577717
			}
Packit 577717
			if (fmt & PERF_FORMAT_ID) {
Packit 577717
				ret = perf_read_buffer_64(hw, &val64);
Packit 577717
				if (ret) {
Packit 577717
					warnx( "cannot read leader id");
Packit 577717
					return -1;
Packit 577717
				}
Packit 577717
				sz -= sizeof(val64);
Packit 577717
			}
Packit 577717
Packit 577717
			fprintf(fp, "ENA=%'"PRIu64" RUN=%'"PRIu64"\n", time_enabled, time_running);
Packit 577717
Packit 577717
			values[0] = val64;
Packit 577717
			values[1] = time_enabled;
Packit 577717
			values[2] = time_running;
Packit 577717
			val64 = perf_scale(values);
Packit 577717
Packit 577717
			fprintf(fp, "\t%'"PRIu64" %s %s\n",
Packit 577717
				val64, fds[0].name,
Packit 577717
				time_running != time_enabled ? ", scaled":"");
Packit 577717
		}
Packit 577717
	}
Packit 577717
Packit 577717
	if (type & PERF_SAMPLE_CALLCHAIN) {
Packit 577717
		uint64_t nr, ip;
Packit 577717
Packit 577717
		ret = perf_read_buffer_64(hw, &nr);
Packit 577717
		if (ret) {
Packit 577717
			warnx( "cannot read callchain nr");
Packit 577717
			return -1;
Packit 577717
		}
Packit 577717
		sz -= sizeof(nr);
Packit 577717
Packit 577717
		while(nr--) {
Packit 577717
			ret = perf_read_buffer_64(hw, &ip);
Packit 577717
			if (ret) {
Packit 577717
				warnx( "cannot read ip");
Packit 577717
				return -1;
Packit 577717
			}
Packit 577717
Packit 577717
			sz -= sizeof(ip);
Packit 577717
Packit 577717
			fprintf(fp, "\t0x%"PRIx64"\n", ip);
Packit 577717
		}
Packit 577717
	}
Packit 577717
Packit 577717
	if (type & PERF_SAMPLE_RAW) {
Packit 577717
		ret = __perf_handle_raw(hw);
Packit 577717
		if (ret == -1)
Packit 577717
			return -1;
Packit 577717
		sz -= ret;
Packit 577717
	}
Packit 577717
Packit 577717
	if (type & PERF_SAMPLE_BRANCH_STACK) {
Packit 577717
		ret = perf_display_branch_stack(hw, fp);
Packit 577717
		sz -= ret;
Packit 577717
	}
Packit 577717
Packit 577717
	if (type & PERF_SAMPLE_REGS_USER) {
Packit 577717
		ret = perf_display_regs_user(hw, fp);
Packit 577717
		sz -= ret;
Packit 577717
	}
Packit 577717
Packit 577717
	if (type & PERF_SAMPLE_STACK_USER) {
Packit 577717
		ret = perf_display_stack_user(hw, fp);
Packit 577717
		sz -= ret;
Packit 577717
	}
Packit 577717
Packit 577717
	if (type & PERF_SAMPLE_WEIGHT) {
Packit 577717
		ret = perf_read_buffer_64(hw, &val64);
Packit 577717
		if (ret) {
Packit 577717
			warnx( "cannot read weight");
Packit 577717
			return -1;
Packit 577717
		}
Packit 577717
		fprintf(fp, "WEIGHT:%'"PRIu64" ", val64);
Packit 577717
		sz -= sizeof(val64);
Packit 577717
	}
Packit 577717
Packit 577717
	if (type & PERF_SAMPLE_DATA_SRC) {
Packit 577717
		ret = perf_read_buffer_64(hw, &val64);
Packit 577717
		if (ret) {
Packit 577717
			warnx( "cannot read data src");
Packit 577717
			return -1;
Packit 577717
		}
Packit 577717
		fprintf(fp, "DATA_SRC:%'"PRIu64" ", val64);
Packit 577717
		sz -= sizeof(val64);
Packit 577717
	}
Packit 577717
	if (type & PERF_SAMPLE_TRANSACTION) {
Packit 577717
		ret = perf_read_buffer_64(hw, &val64);
Packit 577717
		if (ret) {
Packit 577717
			warnx( "cannot read txn");
Packit 577717
			return -1;
Packit 577717
		}
Packit 577717
		fprintf(fp, "TXN:%'"PRIu64" ", val64);
Packit 577717
		sz -= sizeof(val64);
Packit 577717
	}
Packit 577717
Packit 577717
	if (type & PERF_SAMPLE_REGS_INTR) {
Packit 577717
		ret = perf_display_regs_intr(hw, fp);
Packit 577717
		sz -= ret;
Packit 577717
	}
Packit 577717
Packit 577717
	/*
Packit 577717
	 * if we have some data left, it is because there is more
Packit 577717
	 * than what we know about. In fact, it is more complicated
Packit 577717
	 * because we may have the right size but wrong layout. But
Packit 577717
	 * that's the best we can do.
Packit 577717
	 */
Packit 577717
	if (sz) {
Packit 577717
		warnx("did not correctly parse sample leftover=%zu", sz);
Packit 577717
		perf_skip_buffer(hw, sz);
Packit 577717
	}
Packit 577717
Packit 577717
	fputc('\n',fp);
Packit 577717
	return 0;
Packit 577717
}
Packit 577717
Packit 577717
uint64_t
Packit 577717
display_lost(perf_event_desc_t *hw, perf_event_desc_t *fds, int num_fds, FILE *fp)
Packit 577717
{
Packit 577717
	struct { uint64_t id, lost; } lost;
Packit 577717
	const char *str;
Packit 577717
	int e, ret;
Packit 577717
Packit 577717
	ret = perf_read_buffer(hw, &lost, sizeof(lost));
Packit 577717
	if (ret) {
Packit 577717
		warnx("cannot read lost info");
Packit 577717
		return 0;
Packit 577717
	}
Packit 577717
Packit 577717
	e = perf_id2event(fds, num_fds, lost.id);
Packit 577717
	if (e == -1)
Packit 577717
		str = "unknown lost event";
Packit 577717
	else
Packit 577717
		str = fds[e].name;
Packit 577717
Packit 577717
	fprintf(fp, "<<<LOST %"PRIu64" SAMPLES FOR EVENT %s>>>\n",
Packit 577717
		lost.lost,
Packit 577717
		str);
Packit 577717
Packit 577717
	return lost.lost;
Packit 577717
}
Packit 577717
Packit 577717
void
Packit 577717
display_exit(perf_event_desc_t *hw, FILE *fp)
Packit 577717
{
Packit 577717
	struct { pid_t pid, ppid, tid, ptid; } grp;
Packit 577717
	int ret;
Packit 577717
Packit 577717
	ret = perf_read_buffer(hw, &grp, sizeof(grp));
Packit 577717
	if (ret) {
Packit 577717
		warnx("cannot read exit info");
Packit 577717
		return;
Packit 577717
	}
Packit 577717
Packit 577717
	fprintf(fp,"[%d] exited\n", grp.pid);
Packit 577717
}
Packit 577717
Packit 577717
void
Packit 577717
display_freq(int mode, perf_event_desc_t *hw, FILE *fp)
Packit 577717
{
Packit 577717
	struct { uint64_t time, id, stream_id; } thr;
Packit 577717
	int ret;
Packit 577717
Packit 577717
	ret = perf_read_buffer(hw, &thr, sizeof(thr));
Packit 577717
	if (ret) {
Packit 577717
		warnx("cannot read throttling info");
Packit 577717
		return;
Packit 577717
	}
Packit 577717
Packit 577717
	fprintf(fp, "%s value=%"PRIu64" event ID=%"PRIu64"\n",
Packit 577717
		mode ? "Throttled" : "Unthrottled",
Packit 577717
		thr.id,
Packit 577717
		thr.stream_id);
Packit 577717
}