static LIST_HEAD(dsos);
static struct dso *kernel_dso;
static struct dso *vdso;
+static struct dso *hypervisor_dso;
static void dsos__add(struct dso *dso)
{
dsos__add(vdso);
+ hypervisor_dso = dso__new("[hypervisor]", 0);
+ if (!hypervisor_dso)
+ return -1;
+ dsos__add(hypervisor_dso);
+
return err;
}
if (self->sym) {
ret += fprintf(fp, "[%c] %s",
- self->dso == kernel_dso ? 'k' : '.', self->sym->name);
+ self->dso == kernel_dso ? 'k' :
+ self->dso == hypervisor_dso ? 'h' : '.', self->sym->name);
} else {
ret += fprintf(fp, "%#016llx", (u64)self->ip);
}
}
switch (context) {
+ case PERF_CONTEXT_HV:
+ dso = hypervisor_dso;
+ break;
case PERF_CONTEXT_KERNEL:
dso = kernel_dso;
break;
struct map *map = NULL;
void *more_data = event->ip.__more_data;
struct ip_callchain *chain = NULL;
+ int cpumode;
if (sample_type & PERF_SAMPLE_PERIOD) {
period = *(u64 *)more_data;
if (comm_list && !strlist__has_entry(comm_list, thread->comm))
return 0;
- if (event->header.misc & PERF_EVENT_MISC_KERNEL) {
+ cpumode = event->header.misc & PERF_EVENT_MISC_CPUMODE_MASK;
+
+ if (cpumode == PERF_EVENT_MISC_KERNEL) {
show = SHOW_KERNEL;
level = 'k';
dprintf(" ...... dso: %s\n", dso->name);
- } else if (event->header.misc & PERF_EVENT_MISC_USER) {
+ } else if (cpumode == PERF_EVENT_MISC_USER) {
show = SHOW_USER;
level = '.';
} else {
show = SHOW_HV;
level = 'H';
+
+ dso = hypervisor_dso;
+
dprintf(" ...... dso: [hypervisor]\n");
}
return NULL;
}
+/* Tag samples to be skipped. */
+char *skip_symbols[] = {
+ "default_idle",
+ "cpu_idle",
+ "enter_idle",
+ "exit_idle",
+ "mwait_idle",
+ "ppc64_runlatch_off",
+ "pseries_dedicated_idle_sleep",
+ NULL
+};
+
static int symbol_filter(struct dso *self, struct symbol *sym)
{
static int filter_match;
struct sym_entry *syme;
const char *name = sym->name;
+ int i;
+
+ /*
+ * ppc64 uses function descriptors and appends a '.' to the
+ * start of every instruction address. Remove it.
+ */
+ if (name[0] == '.')
+ name++;
if (!strcmp(name, "_text") ||
!strcmp(name, "_etext") ||
return 1;
syme = dso__sym_priv(self, sym);
- /* Tag samples to be skipped. */
- if (!strcmp("default_idle", name) ||
- !strcmp("cpu_idle", name) ||
- !strcmp("enter_idle", name) ||
- !strcmp("exit_idle", name) ||
- !strcmp("mwait_idle", name))
- syme->skip = 1;
+ for (i = 0; skip_symbols[i]; i++) {
+ if (!strcmp(skip_symbols[i], name)) {
+ syme->skip = 1;
+ break;
+ }
+ }
if (filter_match == 1) {
filter_end = sym->start;
"put the counters into a counter group"),
OPT_STRING('s', "sym-filter", &sym_filter, "pattern",
"only display symbols matchig this pattern"),
- OPT_BOOLEAN('z', "zero", &group,
+ OPT_BOOLEAN('z', "zero", &zero,
"zero history across updates"),
OPT_INTEGER('F', "freq", &freq,
"profile at this frequency"),