perf: 'perf kvm' tool for monitoring guest performance from host

Here is the patch of userspace perf tool.

Signed-off-by: Zhang Yanmin <yanmin_zhang@linux.intel.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
This commit is contained in:
Zhang, Yanmin
2010-04-19 13:32:50 +08:00
committed by Avi Kivity
parent ff9d07a0e7
commit a1645ce12a
30 changed files with 1407 additions and 316 deletions

View File

@@ -67,6 +67,17 @@ void perf_session__update_sample_type(struct perf_session *self)
self->sample_type = perf_header__sample_type(&self->header);
}
int perf_session__create_kernel_maps(struct perf_session *self)
{
int ret;
struct rb_root *root = &self->kerninfo_root;
ret = map_groups__create_kernel_maps(root, HOST_KERNEL_ID);
if (ret >= 0)
ret = map_groups__create_guest_kernel_maps(root);
return ret;
}
struct perf_session *perf_session__new(const char *filename, int mode, bool force)
{
size_t len = filename ? strlen(filename) + 1 : 0;
@@ -86,7 +97,7 @@ struct perf_session *perf_session__new(const char *filename, int mode, bool forc
self->cwd = NULL;
self->cwdlen = 0;
self->unknown_events = 0;
map_groups__init(&self->kmaps);
self->kerninfo_root = RB_ROOT;
if (mode == O_RDONLY) {
if (perf_session__open(self, force) < 0)
@@ -157,8 +168,9 @@ struct map_symbol *perf_session__resolve_callchain(struct perf_session *self,
continue;
}
al.filtered = false;
thread__find_addr_location(thread, self, cpumode,
MAP__FUNCTION, ip, &al, NULL);
MAP__FUNCTION, thread->pid, ip, &al, NULL);
if (al.sym != NULL) {
if (sort__has_parent && !*parent &&
symbol__match_parent_regex(al.sym))
@@ -399,46 +411,6 @@ void perf_event_header__bswap(struct perf_event_header *self)
self->size = bswap_16(self->size);
}
int perf_header__read_build_ids(struct perf_header *self,
int input, u64 offset, u64 size)
{
struct build_id_event bev;
char filename[PATH_MAX];
u64 limit = offset + size;
int err = -1;
while (offset < limit) {
struct dso *dso;
ssize_t len;
struct list_head *head = &dsos__user;
if (read(input, &bev, sizeof(bev)) != sizeof(bev))
goto out;
if (self->needs_swap)
perf_event_header__bswap(&bev.header);
len = bev.header.size - sizeof(bev);
if (read(input, filename, len) != len)
goto out;
if (bev.header.misc & PERF_RECORD_MISC_KERNEL)
head = &dsos__kernel;
dso = __dsos__findnew(head, filename);
if (dso != NULL) {
dso__set_build_id(dso, &bev.build_id);
if (head == &dsos__kernel && filename[0] == '[')
dso->kernel = 1;
}
offset += bev.header.size;
}
err = 0;
out:
return err;
}
static struct thread *perf_session__register_idle_thread(struct perf_session *self)
{
struct thread *thread = perf_session__findnew(self, 0);
@@ -690,26 +662,33 @@ bool perf_session__has_traces(struct perf_session *self, const char *msg)
return true;
}
int perf_session__set_kallsyms_ref_reloc_sym(struct perf_session *self,
int perf_session__set_kallsyms_ref_reloc_sym(struct map **maps,
const char *symbol_name,
u64 addr)
{
char *bracket;
enum map_type i;
struct ref_reloc_sym *ref;
self->ref_reloc_sym.name = strdup(symbol_name);
if (self->ref_reloc_sym.name == NULL)
ref = zalloc(sizeof(struct ref_reloc_sym));
if (ref == NULL)
return -ENOMEM;
bracket = strchr(self->ref_reloc_sym.name, ']');
ref->name = strdup(symbol_name);
if (ref->name == NULL) {
free(ref);
return -ENOMEM;
}
bracket = strchr(ref->name, ']');
if (bracket)
*bracket = '\0';
self->ref_reloc_sym.addr = addr;
ref->addr = addr;
for (i = 0; i < MAP__NR_TYPES; ++i) {
struct kmap *kmap = map__kmap(self->vmlinux_maps[i]);
kmap->ref_reloc_sym = &self->ref_reloc_sym;
struct kmap *kmap = map__kmap(maps[i]);
kmap->ref_reloc_sym = ref;
}
return 0;