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;
samples--;
}
-static void process_event(u64 ip, int counter)
+static void process_event(u64 ip, int counter, int user)
{
samples++;
- if (ip < min_ip || ip > max_ip) {
+ if (user) {
userspace_samples++;
return;
}
old += size;
- if (event->header.misc & PERF_EVENT_MISC_OVERFLOW) {
- if (event->header.type & PERF_SAMPLE_IP)
- process_event(event->ip.ip, md->counter);
+ if (event->header.type == PERF_EVENT_SAMPLE) {
+ int user =
+ (event->header.misc & PERF_EVENT_MISC_CPUMODE_MASK) == PERF_EVENT_MISC_USER;
+ process_event(event->ip.ip, md->counter, user);
}
}
"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"),