xenalyze: add to tools/xentrace/

This merges xenalyze.hg, changeset 150:24308507be1d,
into tools/xentrace/xenalyze.c to have the tool and
public/trace.h in one place.

Adjust code to use public/trace.h instead of private trace.h

Signed-off-by: Olaf Hering <olaf@aepfle.de>
Acked-by: Wei Liu <wei.liu2@citrix.com>
Acked-by: George Dunlap <george.dunlap@eu.citrix.com>
Cc: Ian Jackson <ian.jackson@eu.citrix.com>
Cc: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Cc: Ian Campbell <ian.campbell@citrix.com>
Cc: Wei Liu <wei.liu2@citrix.com>
[ ijc -- wrap $(BIN) install in a check in case it is empty (which it
	 is on !x86, avoid BIN += since it results in BIN = ' ' on
         !x86 ]
This commit is contained in:
Olaf Hering authored and Ian Campbell committed 2015-06-16 11:34:59 +01:00
1 parent 2fdf3c433a
commit fd19a9976e
7 files changed
+10742 -1

No files matched your search

+1
View File
@@ -173,6 +173,7 @@ tools/misc/gtracestat
tools/misc/xenlockprof
tools/misc/lowmemd
tools/misc/xencov
tools/xentrace/xenalyze
tools/pygrub/build/*
tools/python/build/*
tools/security/secpol_tool
+8 -1
View File
@@ -6,7 +6,8 @@ CFLAGS += -Werror
CFLAGS += $(CFLAGS_libxenctrl)
LDLIBS += $(LDLIBS_libxenctrl)
BIN =
BIN-$(CONFIG_X86) = xenalyze
BIN = $(BIN-y)
SBIN = xentrace xentrace_setsize
LIBBIN = xenctx
SCRIPTS = xentrace_format
@@ -26,6 +27,9 @@ install: build
[ -z "$(LIBBIN)" ] || $(INSTALL_DIR) $(DESTDIR)$(LIBEXEC_BIN)
$(INSTALL_DIR) $(DESTDIR)$(MAN1DIR)
$(INSTALL_DIR) $(DESTDIR)$(MAN8DIR)
ifneq ($(BIN),)
$(INSTALL_PROG) $(BIN) $(DESTDIR)$(bindir)
endif
$(INSTALL_PROG) $(SBIN) $(DESTDIR)$(sbindir)
$(INSTALL_PYTHON_PROG) $(SCRIPTS) $(DESTDIR)$(bindir)
[ -z "$(LIBBIN)" ] || $(INSTALL_PROG) $(LIBBIN) $(DESTDIR)$(LIBEXEC_BIN)
@@ -48,5 +52,8 @@ xenctx: xenctx.o
xentrace_setsize: setsize.o
$(CC) $(LDFLAGS) -o $@ $< $(LDLIBS) $(APPEND_LDFLAGS)
xenalyze: xenalyze.o mread.o
$(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS) $(APPEND_LDFLAGS)
-include $(DEPS)
+107
View File
@@ -0,0 +1,107 @@
#ifndef __ANALYZE_H
# define __ANALYZE_H
#include <stdint.h>
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
#define TRC_GEN_MAIN 0
#define TRC_SCHED_MAIN 1
#define TRC_DOM0OP_MAIN 2
#define TRC_HVM_MAIN 3
#define TRC_MEM_MAIN 4
#define TRC_PV_MAIN 5
#define TRC_SHADOW_MAIN 6
#define TRC_HW_MAIN 7
#define TRC_LOST_RECORDS_END (TRC_GEN + 50)
#define NR_CPUS 128
#if __x86_64__
# define BITS_PER_LONG 64
#else
# define BITS_PER_LONG 32
#endif
#define BITS_TO_LONGS(bits) \
(((bits)+BITS_PER_LONG-1)/BITS_PER_LONG)
#define DECLARE_BITMAP(name,bits) \
unsigned long name[BITS_TO_LONGS(bits)]
typedef struct cpumask{ DECLARE_BITMAP(bits, NR_CPUS); } cpumask_t;
enum {
TRCE_SFLAG_SET_AD,
TRCE_SFLAG_SET_A,
TRCE_SFLAG_SHADOW_L1_GET_REF,
TRCE_SFLAG_SHADOW_L1_PUT_REF,
TRCE_SFLAG_L2_PROPAGATE,
TRCE_SFLAG_SET_CHANGED,
TRCE_SFLAG_SET_FLUSH,
TRCE_SFLAG_SET_ERROR,
TRCE_SFLAG_DEMOTE,
TRCE_SFLAG_PROMOTE,
TRCE_SFLAG_WRMAP,
TRCE_SFLAG_WRMAP_GUESS_FOUND,
TRCE_SFLAG_WRMAP_BRUTE_FORCE,
TRCE_SFLAG_EARLY_UNSHADOW,
TRCE_SFLAG_EMULATION_2ND_PT_WRITTEN,
TRCE_SFLAG_EMULATION_LAST_FAILED,
TRCE_SFLAG_EMULATE_FULL_PT,
TRCE_SFLAG_PREALLOC_UNPIN,
TRCE_SFLAG_PREALLOC_UNHOOK
};
#define TRC_HVM_OP_DESTROY_PROC (TRC_HVM_HANDLER + 0x100)
typedef unsigned long long tsc_t;
/* -- on-disk trace buffer definitions -- */
struct trace_record {
union {
struct {
unsigned event:28,
extra_words:3,
cycle_flag:1;
union {
struct {
uint32_t tsc_lo, tsc_hi;
uint32_t data[7];
} tsc;
struct {
uint32_t data[7];
} notsc;
} u;
};
uint32_t raw[8];
};
};
/* -- General info about a current record -- */
struct time_struct {
unsigned long long time;
unsigned int s, ns;
};
#define DUMP_HEADER_MAX 256
struct record_info {
int cpu;
tsc_t tsc;
union {
unsigned event;
struct {
unsigned minor:12,
sub:4,
main:12,
unused:4;
} evt;
};
int extra_words;
int size;
uint32_t *d;
char dump_header[DUMP_HEADER_MAX];
struct time_struct t;
struct trace_record rec;
};
#endif
+160
View File
@@ -0,0 +1,160 @@
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <errno.h>
#include "mread.h"
mread_handle_t mread_init(int fd)
{
struct stat64 s;
mread_handle_t h;
h=malloc(sizeof(struct mread_ctrl));
if (!h)
{
perror("malloc");
exit(1);
}
bzero(h, sizeof(struct mread_ctrl));
h->fd = fd;
fstat64(fd, &s);
h->file_size = s.st_size;
return h;
}
ssize_t mread64(mread_handle_t h, void *rec, ssize_t len, loff_t offset)
{
/* Idea: have a "cache" of N mmaped regions. If the offset is
* in one of the regions, just copy it. If not, evict one of the
* regions and map the appropriate range.
*
* Basic algorithm:
* - See if the offset is in one of the regions
* - If not, map it
* - evict an old region
* - map the new region
* - Copy
*/
char * b=NULL;
int bind=-1;
loff_t boffset=0;
ssize_t bsize;
#define dprintf(x...)
//#define dprintf fprintf
dprintf(warn, "%s: offset %llx len %d\n", __func__,
offset, len);
if ( offset > h->file_size )
{
dprintf(warn, " offset > file size %llx, returning 0\n",
h->file_size);
return 0;
}
if ( offset + len > h->file_size )
{
dprintf(warn, " offset+len > file size %llx, truncating\n",
h->file_size);
len = h->file_size - offset;
}
/* Try to find the offset in our range */
dprintf(warn, " Trying last, %d\n", last);
if ( h->map[h->last].buffer
&& (offset & MREAD_BUF_MASK) == h->map[h->last].start_offset )
{
bind=h->last;
goto copy;
}
/* Scan to see if it's anywhere else */
dprintf(warn, " Scanning\n");
for(bind=0; bind<MREAD_MAPS; bind++)
if ( h->map[bind].buffer
&& (offset & MREAD_BUF_MASK) == h->map[bind].start_offset )
{
dprintf(warn, " Found, index %d\n", bind);
break;
}
/* If we didn't find it, evict someone and map it */
if ( bind == MREAD_MAPS )
{
dprintf(warn, " Clock\n");
while(1)
{
h->clock++;
if(h->clock >= MREAD_MAPS)
h->clock=0;
dprintf(warn, " %d\n", h->clock);
if(h->map[h->clock].buffer == NULL)
{
dprintf(warn, " Buffer null, using\n");
break;
}
if(!h->map[h->clock].accessed)
{
dprintf(warn, " Not accessed, using\n");
break;
}
h->map[h->clock].accessed=0;
}
if(h->map[h->clock].buffer)
{
dprintf(warn, " Unmapping\n");
munmap(h->map[h->clock].buffer, MREAD_BUF_SIZE);
}
/* FIXME: Try MAP_HUGETLB? */
/* FIXME: Make sure this works on large files... */
h->map[h->clock].start_offset = offset & MREAD_BUF_MASK;
dprintf(warn, " Mapping %llx from offset %llx\n",
MREAD_BUF_SIZE, h->map[h->clock].start_offset);
h->map[h->clock].buffer = mmap(NULL, MREAD_BUF_SIZE, PROT_READ,
MAP_SHARED,
h->fd,
h->map[h->clock].start_offset);
dprintf(warn, " mmap returned %p\n", h->map[h->clock].buffer);
if ( h->map[h->clock].buffer == MAP_FAILED )
{
h->map[h->clock].buffer = NULL;
perror("mmap");
exit(1);
}
bind = h->clock;
}
h->last=bind;
copy:
h->map[bind].accessed=1;
b=h->map[bind].buffer;
boffset=offset - h->map[bind].start_offset;
if ( boffset + len > MREAD_BUF_SIZE )
bsize = MREAD_BUF_SIZE - boffset;
else
bsize = len;
dprintf(warn, " Using index %d, buffer at %p, buffer offset %llx len %d\n",
bind, b, boffset, bsize);
bcopy(b+boffset, rec, bsize);
/* Handle the boundary case; make sure this is after doing anything
* with the static variables*/
if ( len > bsize )
{
dprintf(warn, " Finishing up by reading l %d o %llx\n",
len-bsize, offset+bsize);
mread64(h, rec+bsize, len-bsize, offset+bsize);
}
/* FIXME: ?? */
return len;
#undef dprintf
}
+18
View File
@@ -0,0 +1,18 @@
#define MREAD_MAPS 8
#define MREAD_BUF_SHIFT 9
#define PAGE_SHIFT 12
#define MREAD_BUF_SIZE (1ULL<<(PAGE_SHIFT+MREAD_BUF_SHIFT))
#define MREAD_BUF_MASK (~(MREAD_BUF_SIZE-1))
typedef struct mread_ctrl {
int fd;
loff_t file_size;
struct mread_buffer {
char * buffer;
loff_t start_offset;
int accessed;
} map[MREAD_MAPS];
int clock, last;
} *mread_handle_t;
mread_handle_t mread_init(int fd);
ssize_t mread64(mread_handle_t h, void *dst, ssize_t len, loff_t offset);
+41
View File
@@ -0,0 +1,41 @@
/*
* PV event decoding.
*
* Copyright (C) 2012 Citrix Systems R&D Ltd.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*/
#ifndef __PV_H
#include "analyze.h"
#include <xen/trace.h>
#ifdef __cplusplus
extern "C" {
#endif
#define ARG_MISSING 0x0
#define ARG_32BIT 0x1
#define ARG_64BIT 0x2
#define MMU_UPDATE_PREEMPTED (~(~0U>>1))
static inline uint32_t pv_hypercall_op(const struct record_info *ri)
{
return ri->d[0] & ~TRC_PV_HYPERCALL_V2_ARG_MASK;
}
static inline int pv_hypercall_arg_present(const struct record_info *ri, int arg)
{
return (ri->d[0] >> (20 + 2*arg)) & 0x3;
}
void pv_hypercall_gather_args(const struct record_info *ri, uint64_t *args);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif
File diff suppressed because it is too large. Load diff
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.