Blame ptdump.c

Packit Service d4effb
/*
Packit Service d4effb
 * Extension module to dump log buffer of Intel(R) Processor Trace
Packit Service d4effb
 *
Packit Service d4effb
 * Copyright (C) 2016 FUJITSU LIMITED
Packit Service d4effb
 *
Packit Service d4effb
 * This program is free software; you can redistribute it and/or modify
Packit Service d4effb
 * it under the terms of the GNU General Public License as published by
Packit Service d4effb
 * the Free Software Foundation; either version 2 of the License, or
Packit Service d4effb
 * (at your option) any later version.
Packit Service d4effb
 *
Packit Service d4effb
 * This program is distributed in the hope that it will be useful,
Packit Service d4effb
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service d4effb
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service d4effb
 * GNU General Public License for more details.
Packit Service d4effb
 */
Packit Service d4effb
Packit Service d4effb
#define _GNU_SOURCE
Packit Service d4effb
#include <sys/file.h>
Packit Service d4effb
Packit Service d4effb
#include "defs.h"
Packit Service d4effb
Packit Service d4effb
#ifdef DEBUG
Packit Service d4effb
#define dbgprintf(...) fprintf(__VA_ARGS__)
Packit Service d4effb
#else
Packit Service d4effb
#define dbgprintf(...) {}
Packit Service d4effb
#endif
Packit Service d4effb
Packit Service d4effb
#define TOPA_SHIFT 12
Packit Service d4effb
Packit Service d4effb
extern int fastdecode(char *, char *);
Packit Service d4effb
Packit Service d4effb
typedef uint8_t  u8;
Packit Service d4effb
typedef uint16_t u16;
Packit Service d4effb
typedef uint32_t u32;
Packit Service d4effb
typedef uint64_t u64;
Packit Service d4effb
Packit Service d4effb
struct topa_entry {
Packit Service d4effb
	u64	end	: 1;
Packit Service d4effb
	u64	rsvd0	: 1;
Packit Service d4effb
	u64	intr	: 1;
Packit Service d4effb
	u64	rsvd1	: 1;
Packit Service d4effb
	u64	stop	: 1;
Packit Service d4effb
	u64	rsvd2	: 1;
Packit Service d4effb
	u64	size	: 4;
Packit Service d4effb
	u64	rsvd3	: 2;
Packit Service d4effb
	u64	base	: 36;
Packit Service d4effb
	u64	rsvd4	: 16;
Packit Service d4effb
};
Packit Service d4effb
Packit Service d4effb
struct pt_info {
Packit Service d4effb
	ulong aux_pages;
Packit Service d4effb
	int aux_nr_pages;
Packit Service d4effb
	ulong pt_buffer;
Packit Service d4effb
Packit Service d4effb
	ulong topa_base;
Packit Service d4effb
	uint topa_idx;
Packit Service d4effb
	ulong output_off;
Packit Service d4effb
Packit Service d4effb
	ulong *buffer_ptr;
Packit Service d4effb
	int curr_buf_idx;
Packit Service d4effb
Packit Service d4effb
	ulong *pt_caps;
Packit Service d4effb
	u32 *cap_regs;
Packit Service d4effb
} *pt_info_list;
Packit Service d4effb
Packit Service d4effb
static inline int
Packit Service d4effb
get_member(ulong addr, char *name, char *member, void* buf)
Packit Service d4effb
{
Packit Service d4effb
	ulong offset, size;
Packit Service d4effb
Packit Service d4effb
	offset = MEMBER_OFFSET(name, member);
Packit Service d4effb
	size = MEMBER_SIZE(name, member);
Packit Service d4effb
Packit Service d4effb
Packit Service d4effb
	if (!readmem(addr + offset, KVADDR, buf, size, name, RETURN_ON_ERROR))
Packit Service d4effb
		return FALSE;
Packit Service d4effb
Packit Service d4effb
	return TRUE;
Packit Service d4effb
}
Packit Service d4effb
Packit Service d4effb
int init_pt_info(int cpu)
Packit Service d4effb
{
Packit Service d4effb
Packit Service d4effb
	ulong struct_pt, struct_handle, struct_ring_buffer;
Packit Service d4effb
	ulong aux_pages, aux_priv;
Packit Service d4effb
	int aux_nr_pages, buf_len;
Packit Service d4effb
	int i, current_buf_idx;
Packit Service d4effb
	struct topa_entry topa;
Packit Service d4effb
	ulong topa_base, output_off, output_base;
Packit Service d4effb
	uint topa_idx;
Packit Service d4effb
	struct pt_info *pt_info_ptr = pt_info_list + cpu;
Packit Service d4effb
Packit Service d4effb
	/* Get pointer to struct pt */
Packit Service d4effb
	if (!symbol_exists("pt_ctx")) {
Packit Service d4effb
		fprintf(fp, "[%d] symbol not found: pt_ctx\n", cpu);
Packit Service d4effb
		return FALSE;
Packit Service d4effb
	}
Packit Service d4effb
	struct_pt = symbol_value("pt_ctx") + kt->__per_cpu_offset[cpu];
Packit Service d4effb
Packit Service d4effb
	/* Get pointer to struct perf_output_handle, struct ring_buffer */
Packit Service d4effb
	struct_handle = struct_pt + MEMBER_OFFSET("pt", "handle");
Packit Service d4effb
	if(!get_member(struct_handle, "perf_output_handle", "rb",
Packit Service d4effb
		       &struct_ring_buffer))
Packit Service d4effb
		return FALSE;
Packit Service d4effb
	if (!struct_ring_buffer) {
Packit Service d4effb
		fprintf(fp, "[%d] ring buffer is zero\n", cpu);
Packit Service d4effb
		return FALSE;
Packit Service d4effb
	}
Packit Service d4effb
Packit Service d4effb
	dbgprintf(fp, "[%d] struct pt=0x%016lx\n", cpu, struct_pt);
Packit Service d4effb
	dbgprintf(fp, "[%d] struct perf_output_handle=0x%016lx\n", cpu,
Packit Service d4effb
		struct_handle);
Packit Service d4effb
	dbgprintf(fp, "[%d] struct ring_buffer=0x%016lx\n", cpu,
Packit Service d4effb
		struct_ring_buffer);
Packit Service d4effb
Packit Service d4effb
	/* symbol access check */
Packit Service d4effb
	if (STRUCT_EXISTS("ring_buffer") &&
Packit Service d4effb
	    !MEMBER_EXISTS("ring_buffer", "aux_pages")) {
Packit Service d4effb
		fprintf(fp, "[%d] invalid ring_buffer\n", cpu);
Packit Service d4effb
		return FALSE;
Packit Service d4effb
	}
Packit Service d4effb
Packit Service d4effb
	/* array of struct pages for pt buffer */
Packit Service d4effb
	if(!get_member(struct_ring_buffer, "ring_buffer", "aux_pages",
Packit Service d4effb
		       &aux_pages))
Packit Service d4effb
		return FALSE;
Packit Service d4effb
Packit Service d4effb
	/* number of pages */
Packit Service d4effb
	if(!get_member(struct_ring_buffer, "ring_buffer", "aux_nr_pages",
Packit Service d4effb
		       &aux_nr_pages))
Packit Service d4effb
		return FALSE;
Packit Service d4effb
Packit Service d4effb
	/* private data (struct pt_buffer) */
Packit Service d4effb
	if(!get_member(struct_ring_buffer, "ring_buffer", "aux_priv",
Packit Service d4effb
		       &aux_priv))
Packit Service d4effb
		return FALSE;
Packit Service d4effb
Packit Service d4effb
	if (!aux_nr_pages) {
Packit Service d4effb
		fprintf(fp, "No aux pages\n");
Packit Service d4effb
		return FALSE;
Packit Service d4effb
	}
Packit Service d4effb
Packit Service d4effb
	pt_info_ptr->aux_pages = aux_pages;
Packit Service d4effb
	pt_info_ptr->aux_nr_pages = aux_nr_pages;
Packit Service d4effb
	pt_info_ptr->pt_buffer = aux_priv;
Packit Service d4effb
Packit Service d4effb
	dbgprintf(fp, "[%d] rb.aux_pages=0x%016lx\n", cpu, aux_pages);
Packit Service d4effb
	dbgprintf(fp, "[%d] rb.aux_nr_pages=0x%d\n", cpu, aux_nr_pages);
Packit Service d4effb
	dbgprintf(fp, "[%d] rb.aux_priv=0x%016lx\n", cpu, aux_priv);
Packit Service d4effb
Packit Service d4effb
	/* Get address of pt buffer */
Packit Service d4effb
	buf_len = sizeof(void*)*aux_nr_pages;
Packit Service d4effb
	pt_info_ptr->buffer_ptr = (ulong *)malloc(buf_len);
Packit Service d4effb
	if (pt_info_ptr->buffer_ptr == NULL) {
Packit Service d4effb
		fprintf(fp, "malloc failed\n");
Packit Service d4effb
		return FALSE;
Packit Service d4effb
	}
Packit Service d4effb
	memset(pt_info_ptr->buffer_ptr, 0, buf_len);
Packit Service d4effb
Packit Service d4effb
	for (i=0; i
Packit Service d4effb
		ulong pgaddr = aux_pages + i*sizeof(void*);
Packit Service d4effb
		ulong page;
Packit Service d4effb
Packit Service d4effb
		if (!readmem(pgaddr, KVADDR, &page, sizeof(ulong),
Packit Service d4effb
			     "struct page", RETURN_ON_ERROR))
Packit Service d4effb
			continue;
Packit Service d4effb
Packit Service d4effb
		pt_info_ptr->buffer_ptr[i] = page;
Packit Service d4effb
Packit Service d4effb
		if (!i)
Packit Service d4effb
			dbgprintf(fp, "[%d] Dump aux pages\n", cpu);
Packit Service d4effb
		dbgprintf(fp, "  %d: 0x%016lx\n", i, page);
Packit Service d4effb
	}
Packit Service d4effb
Packit Service d4effb
	/* Get pt registes saved on panic */
Packit Service d4effb
	if(!get_member(pt_info_ptr->pt_buffer, "pt_buffer", "cur",
Packit Service d4effb
		       &topa_base))
Packit Service d4effb
		goto out_error;
Packit Service d4effb
	if(!get_member(pt_info_ptr->pt_buffer, "pt_buffer", "cur_idx",
Packit Service d4effb
		       &topa_idx))
Packit Service d4effb
		goto out_error;
Packit Service d4effb
	if(!get_member(pt_info_ptr->pt_buffer, "pt_buffer", "output_off",
Packit Service d4effb
		       &output_off))
Packit Service d4effb
		goto out_error;
Packit Service d4effb
Packit Service d4effb
	dbgprintf(fp, "[%d] buf.cur=0x%016lx\n", cpu, topa_base);
Packit Service d4effb
	dbgprintf(fp, "[%d] buf.cur_idx=0x%08x\n", cpu, topa_idx);
Packit Service d4effb
	dbgprintf(fp, "[%d] buf.output_off=0x%016lx\n", cpu, output_off);
Packit Service d4effb
Packit Service d4effb
	pt_info_ptr->topa_base = topa_base;
Packit Service d4effb
	pt_info_ptr->topa_idx = topa_idx;
Packit Service d4effb
	pt_info_ptr->output_off = output_off;
Packit Service d4effb
Packit Service d4effb
	/* Read topa entry */
Packit Service d4effb
	if (!readmem((topa_base) + topa_idx*(sizeof(struct topa_entry)),
Packit Service d4effb
		     KVADDR, &topa, sizeof(topa),
Packit Service d4effb
		     "struct topa_entry", RETURN_ON_ERROR)) {
Packit Service d4effb
		fprintf(fp, "Cannot read topa table\n");
Packit Service d4effb
		goto out_error;
Packit Service d4effb
	}
Packit Service d4effb
Packit Service d4effb
	dbgprintf(fp, "[%d] topa.end=%d\n", cpu, topa.end);
Packit Service d4effb
	dbgprintf(fp, "[%d] topa.intr=%d\n", cpu, topa.intr);
Packit Service d4effb
	dbgprintf(fp, "[%d] topa.stop=%d\n", cpu, topa.stop);
Packit Service d4effb
	dbgprintf(fp, "[%d] topa.size=%d\n", cpu, topa.size);
Packit Service d4effb
	dbgprintf(fp, "[%d] topa.base=0x%016lx\n", cpu, (ulong)topa.base);
Packit Service d4effb
Packit Service d4effb
	/*
Packit Service d4effb
	 * Find buffer page which is currently used.
Packit Service d4effb
	 */
Packit Service d4effb
	output_base = (u64)(topa.base)<
Packit Service d4effb
	current_buf_idx = -1;
Packit Service d4effb
	for (i=0; i
Packit Service d4effb
		if (VTOP(pt_info_ptr->buffer_ptr[i]) == output_base) {
Packit Service d4effb
			current_buf_idx = i;
Packit Service d4effb
			break;
Packit Service d4effb
		}
Packit Service d4effb
	}
Packit Service d4effb
Packit Service d4effb
	if (current_buf_idx == -1) {
Packit Service d4effb
		fprintf(fp, "current buffer not found\n");
Packit Service d4effb
		goto out_error;
Packit Service d4effb
	}
Packit Service d4effb
Packit Service d4effb
	pt_info_ptr->curr_buf_idx = current_buf_idx;
Packit Service d4effb
	dbgprintf(fp, "[%d] current bufidx=%d\n", cpu, current_buf_idx);
Packit Service d4effb
Packit Service d4effb
	return TRUE;
Packit Service d4effb
Packit Service d4effb
out_error:
Packit Service d4effb
	if (pt_info_ptr->buffer_ptr != NULL)
Packit Service d4effb
		free(pt_info_ptr->buffer_ptr);
Packit Service d4effb
Packit Service d4effb
	return FALSE;
Packit Service d4effb
}
Packit Service d4effb
Packit Service d4effb
static inline int is_zero_page(ulong page, int offset)
Packit Service d4effb
{
Packit Service d4effb
	ulong read_addr = page + offset;
Packit Service d4effb
	ulong read_size = PAGESIZE() - offset;
Packit Service d4effb
	char *buf = malloc(PAGESIZE());
Packit Service d4effb
	int i;
Packit Service d4effb
Packit Service d4effb
	if (buf == NULL) {
Packit Service d4effb
		fprintf(fp, "malloc failed\n");
Packit Service d4effb
		return FALSE;
Packit Service d4effb
	}
Packit Service d4effb
Packit Service d4effb
	memset(buf, 0, PAGESIZE());
Packit Service d4effb
	dbgprintf(fp, "zero page chk: 0x%016lx, %lu\n", read_addr, read_size);
Packit Service d4effb
	if (!readmem(read_addr, KVADDR, buf, read_size, "zero page check",
Packit Service d4effb
		     RETURN_ON_ERROR)) {
Packit Service d4effb
		free(buf);
Packit Service d4effb
		return FALSE;
Packit Service d4effb
	}
Packit Service d4effb
Packit Service d4effb
	for (i = 0; i < PAGESIZE() - offset; i++) {
Packit Service d4effb
		if (buf[i]) {
Packit Service d4effb
			free(buf);
Packit Service d4effb
			return FALSE;
Packit Service d4effb
		}
Packit Service d4effb
	}
Packit Service d4effb
Packit Service d4effb
	free(buf);
Packit Service d4effb
	return TRUE;
Packit Service d4effb
}
Packit Service d4effb
Packit Service d4effb
int check_wrap_around(int cpu)
Packit Service d4effb
{
Packit Service d4effb
	struct pt_info *pt_info_ptr = pt_info_list + cpu;
Packit Service d4effb
	int wrapped = 0, i, page_idx;
Packit Service d4effb
	ulong offset, mask, page;
Packit Service d4effb
Packit Service d4effb
	mask = (((ulong)1)<
Packit Service d4effb
	offset = pt_info_ptr->output_off & mask;
Packit Service d4effb
	page_idx = pt_info_ptr->curr_buf_idx +
Packit Service d4effb
		   (pt_info_ptr->output_off >> PAGESHIFT());
Packit Service d4effb
Packit Service d4effb
	dbgprintf(fp, "[%d] buf: mask=0x%lx\n", cpu, mask);
Packit Service d4effb
	dbgprintf(fp, "[%d] buf: offset=0x%lx\n", cpu, offset);
Packit Service d4effb
	dbgprintf(fp, "[%d] buf: page_idx=%d\n", cpu, page_idx);
Packit Service d4effb
Packit Service d4effb
	for (i=page_idx; i<pt_info_ptr->aux_nr_pages; i++) {
Packit Service d4effb
		page = pt_info_ptr->buffer_ptr[i];
Packit Service d4effb
Packit Service d4effb
		if (!is_zero_page(page, offset)) {
Packit Service d4effb
			wrapped = 1;
Packit Service d4effb
			break;
Packit Service d4effb
		}
Packit Service d4effb
Packit Service d4effb
		offset = 0;
Packit Service d4effb
	}
Packit Service d4effb
Packit Service d4effb
	return wrapped;
Packit Service d4effb
}
Packit Service d4effb
Packit Service d4effb
int write_buffer_wrapped(int cpu, FILE *out_fp)
Packit Service d4effb
{
Packit Service d4effb
	struct pt_info *pt_info_ptr = pt_info_list + cpu;
Packit Service d4effb
	int start_idx, idx, len, ret;
Packit Service d4effb
	ulong mask, offset, page;
Packit Service d4effb
	char *buf = malloc(PAGESIZE());
Packit Service d4effb
Packit Service d4effb
	if (buf == NULL) {
Packit Service d4effb
		fprintf(fp, "malloc failed\n");
Packit Service d4effb
		return FALSE;
Packit Service d4effb
	}
Packit Service d4effb
Packit Service d4effb
	mask = (((ulong)1)<
Packit Service d4effb
	offset = pt_info_ptr->output_off & mask;
Packit Service d4effb
Packit Service d4effb
	start_idx = pt_info_ptr->curr_buf_idx +
Packit Service d4effb
	   (pt_info_ptr->output_off >> PAGESHIFT());
Packit Service d4effb
Packit Service d4effb
	for (idx = start_idx; idx<pt_info_ptr->aux_nr_pages; idx++) {
Packit Service d4effb
		page = pt_info_ptr->buffer_ptr[idx];
Packit Service d4effb
		len = PAGESIZE() - offset;
Packit Service d4effb
Packit Service d4effb
		if (!readmem(page + offset, KVADDR, buf, len, "read page for write",
Packit Service d4effb
			     RETURN_ON_ERROR)) {
Packit Service d4effb
			free(buf);
Packit Service d4effb
			return FALSE;
Packit Service d4effb
		}
Packit Service d4effb
Packit Service d4effb
		dbgprintf(fp, "[%d] R/W1 buff: p=0x%lx, i=%d, o=%lu, l=%d\n",
Packit Service d4effb
			cpu, page + offset, idx, offset, len);
Packit Service d4effb
Packit Service d4effb
		ret = fwrite(buf, len, 1, out_fp);
Packit Service d4effb
		if (!ret) {
Packit Service d4effb
			fprintf(fp, "[%d] Cannot write file\n", cpu);
Packit Service d4effb
			free(buf);
Packit Service d4effb
			return FALSE;
Packit Service d4effb
		}
Packit Service d4effb
Packit Service d4effb
		offset = 0;
Packit Service d4effb
	}
Packit Service d4effb
Packit Service d4effb
	for (idx = 0; idx < start_idx; idx++) {
Packit Service d4effb
		page = pt_info_ptr->buffer_ptr[idx];
Packit Service d4effb
		len = PAGESIZE() - offset;
Packit Service d4effb
Packit Service d4effb
		if (!readmem(page + offset, KVADDR, buf, len, "read page for write",
Packit Service d4effb
			     RETURN_ON_ERROR)) {
Packit Service d4effb
			free(buf);
Packit Service d4effb
			return FALSE;
Packit Service d4effb
		}
Packit Service d4effb
Packit Service d4effb
		dbgprintf(fp, "[%d] R/W2 buff: p=0x%lx, i=%d, o=%lu, l=%d\n",
Packit Service d4effb
			cpu, page + offset, idx, offset, len);
Packit Service d4effb
Packit Service d4effb
		ret = fwrite(buf, len, 1, out_fp);
Packit Service d4effb
		if (!ret) {
Packit Service d4effb
			fprintf(fp, "[%d] Cannot write file\n", cpu);
Packit Service d4effb
			free(buf);
Packit Service d4effb
			return FALSE;
Packit Service d4effb
		}
Packit Service d4effb
	}
Packit Service d4effb
Packit Service d4effb
	idx = start_idx;
Packit Service d4effb
	page = pt_info_ptr->buffer_ptr[idx];
Packit Service d4effb
	offset = pt_info_ptr->output_off & mask;
Packit Service d4effb
	len = offset;
Packit Service d4effb
Packit Service d4effb
	if (!len)
Packit Service d4effb
		goto done;
Packit Service d4effb
Packit Service d4effb
	if (!readmem(page, KVADDR, buf, len, "read page for write",
Packit Service d4effb
		     RETURN_ON_ERROR)) {
Packit Service d4effb
		free(buf);
Packit Service d4effb
		return FALSE;
Packit Service d4effb
	}
Packit Service d4effb
Packit Service d4effb
	dbgprintf(fp, "[%d] R/W3 buff: p=0x%lx, i=%d, o=%lu, l=%d\n", cpu,
Packit Service d4effb
		page, idx, offset, len);
Packit Service d4effb
Packit Service d4effb
	ret = fwrite(buf, len, 1, out_fp);
Packit Service d4effb
	if (!ret) {
Packit Service d4effb
		fprintf(fp, "[%d] Cannot write file\n", cpu);
Packit Service d4effb
		free(buf);
Packit Service d4effb
		return FALSE;
Packit Service d4effb
	}
Packit Service d4effb
Packit Service d4effb
done:
Packit Service d4effb
	free(buf);
Packit Service d4effb
	return TRUE;
Packit Service d4effb
}
Packit Service d4effb
Packit Service d4effb
int write_buffer_nowrapped(int cpu, FILE *out_fp)
Packit Service d4effb
{
Packit Service d4effb
	struct pt_info *pt_info_ptr = pt_info_list + cpu;
Packit Service d4effb
	int last_idx, idx, len, ret;
Packit Service d4effb
	ulong mask, page;
Packit Service d4effb
	char *buf = malloc(PAGESIZE());
Packit Service d4effb
Packit Service d4effb
	if (buf == NULL) {
Packit Service d4effb
		fprintf(fp, "malloc failed\n");
Packit Service d4effb
		return FALSE;
Packit Service d4effb
	}
Packit Service d4effb
Packit Service d4effb
	mask = (((ulong)1)<
Packit Service d4effb
	last_idx = pt_info_ptr->curr_buf_idx +
Packit Service d4effb
	   (pt_info_ptr->output_off >> PAGESHIFT());
Packit Service d4effb
Packit Service d4effb
	for (idx = 0; idx < last_idx; idx++) {
Packit Service d4effb
		page = pt_info_ptr->buffer_ptr[idx];
Packit Service d4effb
		len = PAGESIZE();
Packit Service d4effb
Packit Service d4effb
		if (!readmem(page, KVADDR, buf, len, "read page for write",
Packit Service d4effb
			     RETURN_ON_ERROR)) {
Packit Service d4effb
			free(buf);
Packit Service d4effb
			return FALSE;
Packit Service d4effb
		}
Packit Service d4effb
Packit Service d4effb
		dbgprintf(fp, "[%d] R/W1 buff: p=0x%lx, i=%d, o=%lu, l=%d\n",
Packit Service d4effb
			cpu, page, idx, (ulong)0, len);
Packit Service d4effb
Packit Service d4effb
		ret = fwrite(buf, len, 1, out_fp);
Packit Service d4effb
		if (!ret) {
Packit Service d4effb
			fprintf(fp, "[%d] Cannot write file\n", cpu);
Packit Service d4effb
			free(buf);
Packit Service d4effb
			return FALSE;
Packit Service d4effb
		}
Packit Service d4effb
	}
Packit Service d4effb
Packit Service d4effb
	idx = last_idx;
Packit Service d4effb
	page = pt_info_ptr->buffer_ptr[idx];
Packit Service d4effb
	len = pt_info_ptr->output_off & mask;
Packit Service d4effb
Packit Service d4effb
	if (!len)
Packit Service d4effb
		goto done;
Packit Service d4effb
Packit Service d4effb
	if (!readmem(page, KVADDR, buf, len, "read page for write",
Packit Service d4effb
		     RETURN_ON_ERROR)) {
Packit Service d4effb
		free(buf);
Packit Service d4effb
		return FALSE;
Packit Service d4effb
	}
Packit Service d4effb
Packit Service d4effb
	dbgprintf(fp, "[%d] R/W2 buff: p=0x%lx, i=%d, o=%lu, l=%d\n", cpu,
Packit Service d4effb
		page, idx, (ulong)0, len);
Packit Service d4effb
Packit Service d4effb
	ret = fwrite(buf, len, 1, out_fp);
Packit Service d4effb
	if (!ret) {
Packit Service d4effb
		fprintf(fp, "[%d] Cannot write file\n", cpu);
Packit Service d4effb
		free(buf);
Packit Service d4effb
		return FALSE;
Packit Service d4effb
	}
Packit Service d4effb
Packit Service d4effb
done:
Packit Service d4effb
	free(buf);
Packit Service d4effb
	return TRUE;
Packit Service d4effb
}
Packit Service d4effb
Packit Service d4effb
int write_pt_log_buffer_cpu(int cpu, char *fname)
Packit Service d4effb
{
Packit Service d4effb
	int wrapped, ret;
Packit Service d4effb
	FILE *out_fp;
Packit Service d4effb
Packit Service d4effb
	wrapped = check_wrap_around(cpu);
Packit Service d4effb
Packit Service d4effb
	if ((out_fp = fopen(fname, "w")) == NULL) {
Packit Service d4effb
		fprintf(fp, "[%d] Cannot open file: %s\n", cpu, fname);
Packit Service d4effb
		return FALSE;
Packit Service d4effb
	}
Packit Service d4effb
	dbgprintf(fp, "[%d] Open file: %s\n", cpu, fname);
Packit Service d4effb
Packit Service d4effb
	/*
Packit Service d4effb
	 * Write buffer to file
Packit Service d4effb
	 *
Packit Service d4effb
	 * Case 1: Not wrapped around
Packit Service d4effb
	 *
Packit Service d4effb
	 *   start       end
Packit Service d4effb
	 *   |           |
Packit Service d4effb
	 *   v           v
Packit Service d4effb
	 *   +------+  +------+     +------+  +------+
Packit Service d4effb
	 *   |buffer|  |buffer| ... |buffer|  |buffer|
Packit Service d4effb
	 *   +------+  +------+     +------+  +------+
Packit Service d4effb
	 *
Packit Service d4effb
	 *   In this case, just write data between 'start' and 'end'
Packit Service d4effb
	 *
Packit Service d4effb
	 * Case 2: Wrapped around
Packit Service d4effb
	 *
Packit Service d4effb
	 *            end start
Packit Service d4effb
	 *             |  |
Packit Service d4effb
	 *             v  v
Packit Service d4effb
	 *   +------+  +------+     +------+  +------+
Packit Service d4effb
	 *   |buffer|  |buffer| ... |buffer|  |buffer|
Packit Service d4effb
	 *   +------+  +------+     +------+  +------+
Packit Service d4effb
	 *
Packit Service d4effb
	 *   In this case, at first write data between 'start' and end of last
Packit Service d4effb
	 *   buffer, and then write data between beginning of first buffer and
Packit Service d4effb
	 *   'end'.
Packit Service d4effb
	 */
Packit Service d4effb
	if (wrapped) {
Packit Service d4effb
		dbgprintf(fp, "[%d] wrap around: true\n", cpu);
Packit Service d4effb
		ret = write_buffer_wrapped(cpu, out_fp);
Packit Service d4effb
	} else {
Packit Service d4effb
		dbgprintf(fp, "[%d] wrap around: false\n", cpu);
Packit Service d4effb
		ret = write_buffer_nowrapped(cpu, out_fp);
Packit Service d4effb
	}
Packit Service d4effb
Packit Service d4effb
	fclose(out_fp);
Packit Service d4effb
	return ret;
Packit Service d4effb
}
Packit Service d4effb
Packit Service d4effb
void
Packit Service d4effb
cmd_ptdump(void)
Packit Service d4effb
{
Packit Service d4effb
	int i, ret, list_len;
Packit Service d4effb
	int online_cpus;
Packit Service d4effb
	char* outdir;
Packit Service d4effb
	char dumpfile[16];
Packit Service d4effb
	char decodefile[16];
Packit Service d4effb
	mode_t mode = S_IRUSR | S_IWUSR | S_IXUSR |
Packit Service d4effb
		      S_IRGRP | S_IXGRP |
Packit Service d4effb
		      S_IROTH | S_IXOTH; /* 0755 */
Packit Service d4effb
	struct pt_info *pt_info_ptr;
Packit Service d4effb
Packit Service d4effb
	if (argcnt != 2)
Packit Service d4effb
		cmd_usage(pc->curcmd, SYNOPSIS);
Packit Service d4effb
Packit Service d4effb
	if (ACTIVE())
Packit Service d4effb
		error(FATAL, "not supported on a live system\n");
Packit Service d4effb
Packit Service d4effb
	outdir = args[1];
Packit Service d4effb
	if ((ret = mkdir(outdir, mode))) {
Packit Service d4effb
		fprintf(fp, "Cannot create directory %s: %d\n", outdir, ret);
Packit Service d4effb
		return;
Packit Service d4effb
	}
Packit Service d4effb
Packit Service d4effb
	if ((ret = chdir(outdir))) {
Packit Service d4effb
		fprintf(fp, "Cannot chdir %s: %d\n", outdir, ret);
Packit Service d4effb
		return;
Packit Service d4effb
	}
Packit Service d4effb
Packit Service d4effb
	/*
Packit Service d4effb
	 * Set the gdb scope to ensure that the appropriate ring_buffer
Packit Service d4effb
	 * structure is selected.
Packit Service d4effb
	 */
Packit Service d4effb
	if (kernel_symbol_exists("perf_mmap_to_page"))
Packit Service d4effb
		gdb_set_crash_scope(symbol_value("perf_mmap_to_page"),
Packit Service d4effb
			"perf_mmap_to_page");
Packit Service d4effb
Packit Service d4effb
	online_cpus = get_cpus_online();
Packit Service d4effb
	list_len = sizeof(struct pt_info)*kt->cpus;
Packit Service d4effb
	pt_info_list = malloc(list_len);
Packit Service d4effb
	if (pt_info_list == NULL) {
Packit Service d4effb
		fprintf(fp, "Cannot alloc pt_info_list\n");
Packit Service d4effb
		return;
Packit Service d4effb
	}
Packit Service d4effb
	memset(pt_info_list, 0, list_len);
Packit Service d4effb
Packit Service d4effb
	for (i = 0; online_cpus > 0; i++) {
Packit Service d4effb
		if (!in_cpu_map(ONLINE_MAP, i))
Packit Service d4effb
			continue;
Packit Service d4effb
Packit Service d4effb
		online_cpus--;
Packit Service d4effb
Packit Service d4effb
		if (!init_pt_info(i))
Packit Service d4effb
			continue;
Packit Service d4effb
Packit Service d4effb
		sprintf(dumpfile, "dump.%d", i);
Packit Service d4effb
		if (write_pt_log_buffer_cpu(i, dumpfile))
Packit Service d4effb
			fprintf(fp, "[%d] buffer dump: %s\n", i, dumpfile);
Packit Service d4effb
Packit Service d4effb
		sprintf(decodefile, "decode.%d", i);
Packit Service d4effb
		if (fastdecode(dumpfile, decodefile))
Packit Service d4effb
			fprintf(fp, "[%d] packet decode: %s\n", i, decodefile);
Packit Service d4effb
Packit Service d4effb
		pt_info_ptr = pt_info_list + i;
Packit Service d4effb
		if (pt_info_ptr->buffer_ptr != NULL)
Packit Service d4effb
			free(pt_info_ptr->buffer_ptr);
Packit Service d4effb
	}
Packit Service d4effb
	free(pt_info_list);
Packit Service d4effb
	chdir("..");
Packit Service d4effb
}
Packit Service d4effb
Packit Service d4effb
char *help_ptdump[] = {
Packit Service d4effb
	"ptdump",
Packit Service d4effb
	"Dump log buffer of Intel(R) Processor Trace",
Packit Service d4effb
	"<output-dir>",
Packit Service d4effb
	"This command extracts log buffer of PT to the directory",
Packit Service d4effb
	"specified by <output-dir>",
Packit Service d4effb
	NULL
Packit Service d4effb
};
Packit Service d4effb
Packit Service d4effb
static struct command_table_entry command_table[] = {
Packit Service d4effb
	{ "ptdump", cmd_ptdump, help_ptdump, 0},
Packit Service d4effb
	{ NULL },
Packit Service d4effb
};
Packit Service d4effb
Packit Service d4effb
void __attribute__((constructor))
Packit Service d4effb
ptdump_init(void)
Packit Service d4effb
{
Packit Service d4effb
	register_extension(command_table);
Packit Service d4effb
}
Packit Service d4effb
Packit Service d4effb
void __attribute__((destructor))
Packit Service d4effb
ptdump_fini(void) { }
Packit Service d4effb