perf hists: Enlarge pid sort entry size
[deliverable/linux.git] / tools / perf / util / evsel.c
index 645dc18288367733567b760f136b81657a5937ef..1d8f2bbd38a793c7089f3461b93428f6cf6eda36 100644 (file)
@@ -37,6 +37,7 @@ static struct {
        bool clockid;
        bool clockid_wrong;
        bool lbr_flags;
+       bool write_backward;
 } perf_missing_features;
 
 static clockid_t clockid;
@@ -226,7 +227,8 @@ struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx)
                perf_evsel__init(evsel, attr, idx);
 
        if (perf_evsel__is_bpf_output(evsel)) {
-               evsel->attr.sample_type |= PERF_SAMPLE_RAW;
+               evsel->attr.sample_type |= (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME |
+                                           PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD),
                evsel->attr.sample_period = 1;
        }
 
@@ -561,16 +563,17 @@ int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size)
        return ret;
 }
 
-static void
-perf_evsel__config_callgraph(struct perf_evsel *evsel,
-                            struct record_opts *opts,
-                            struct callchain_param *param)
+void perf_evsel__config_callchain(struct perf_evsel *evsel,
+                                 struct record_opts *opts,
+                                 struct callchain_param *param)
 {
        bool function = perf_evsel__is_function_event(evsel);
        struct perf_event_attr *attr = &evsel->attr;
 
        perf_evsel__set_sample_bit(evsel, CALLCHAIN);
 
+       attr->sample_max_stack = param->max_stack;
+
        if (param->record_mode == CALLCHAIN_LBR) {
                if (!opts->branch_stack) {
                        if (attr->exclude_user) {
@@ -634,7 +637,8 @@ static void apply_config_terms(struct perf_evsel *evsel,
        struct perf_event_attr *attr = &evsel->attr;
        struct callchain_param param;
        u32 dump_size = 0;
-       char *callgraph_buf = NULL;
+       int max_stack = 0;
+       const char *callgraph_buf = NULL;
 
        /* callgraph default */
        param.record_mode = callchain_param.record_mode;
@@ -661,6 +665,9 @@ static void apply_config_terms(struct perf_evsel *evsel,
                case PERF_EVSEL__CONFIG_TERM_STACK_USER:
                        dump_size = term->val.stack_user;
                        break;
+               case PERF_EVSEL__CONFIG_TERM_MAX_STACK:
+                       max_stack = term->val.max_stack;
+                       break;
                case PERF_EVSEL__CONFIG_TERM_INHERIT:
                        /*
                         * attr->inherit should has already been set by
@@ -676,7 +683,12 @@ static void apply_config_terms(struct perf_evsel *evsel,
        }
 
        /* User explicitly set per-event callgraph, clear the old setting and reset. */
-       if ((callgraph_buf != NULL) || (dump_size > 0)) {
+       if ((callgraph_buf != NULL) || (dump_size > 0) || max_stack) {
+               if (max_stack) {
+                       param.max_stack = max_stack;
+                       if (callgraph_buf == NULL)
+                               callgraph_buf = "fp";
+               }
 
                /* parse callgraph parameters */
                if (callgraph_buf != NULL) {
@@ -704,7 +716,7 @@ static void apply_config_terms(struct perf_evsel *evsel,
 
                /* set perf-event callgraph */
                if (param.enabled)
-                       perf_evsel__config_callgraph(evsel, opts, &param);
+                       perf_evsel__config_callchain(evsel, opts, &param);
        }
 }
 
@@ -736,7 +748,8 @@ static void apply_config_terms(struct perf_evsel *evsel,
  *     enable/disable events specifically, as there's no
  *     initial traced exec call.
  */
-void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
+void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts,
+                       struct callchain_param *callchain)
 {
        struct perf_evsel *leader = evsel->leader;
        struct perf_event_attr *attr = &evsel->attr;
@@ -811,8 +824,8 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
        if (perf_evsel__is_function_event(evsel))
                evsel->attr.exclude_callchain_user = 1;
 
-       if (callchain_param.enabled && !evsel->no_aux_samples)
-               perf_evsel__config_callgraph(evsel, opts, &callchain_param);
+       if (callchain && callchain->enabled && !evsel->no_aux_samples)
+               perf_evsel__config_callchain(evsel, opts, callchain);
 
        if (opts->sample_intr_regs) {
                attr->sample_regs_intr = opts->sample_intr_regs;
@@ -826,7 +839,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
                perf_evsel__set_sample_bit(evsel, PERIOD);
 
        /*
-        * When the user explicitely disabled time don't force it here.
+        * When the user explicitly disabled time don't force it here.
         */
        if (opts->sample_time &&
            (!perf_missing_features.sample_id_all &&
@@ -1230,6 +1243,21 @@ static void __p_sample_type(char *buf, size_t size, u64 value)
        __p_bits(buf, size, value, bits);
 }
 
+static void __p_branch_sample_type(char *buf, size_t size, u64 value)
+{
+#define bit_name(n) { PERF_SAMPLE_BRANCH_##n, #n }
+       struct bit_names bits[] = {
+               bit_name(USER), bit_name(KERNEL), bit_name(HV), bit_name(ANY),
+               bit_name(ANY_CALL), bit_name(ANY_RETURN), bit_name(IND_CALL),
+               bit_name(ABORT_TX), bit_name(IN_TX), bit_name(NO_TX),
+               bit_name(COND), bit_name(CALL_STACK), bit_name(IND_JUMP),
+               bit_name(CALL), bit_name(NO_FLAGS), bit_name(NO_CYCLES),
+               { .name = NULL, }
+       };
+#undef bit_name
+       __p_bits(buf, size, value, bits);
+}
+
 static void __p_read_format(char *buf, size_t size, u64 value)
 {
 #define bit_name(n) { PERF_FORMAT_##n, #n }
@@ -1248,6 +1276,7 @@ static void __p_read_format(char *buf, size_t size, u64 value)
 #define p_unsigned(val)                snprintf(buf, BUF_SIZE, "%"PRIu64, (uint64_t)(val))
 #define p_signed(val)          snprintf(buf, BUF_SIZE, "%"PRId64, (int64_t)(val))
 #define p_sample_type(val)     __p_sample_type(buf, BUF_SIZE, val)
+#define p_branch_sample_type(val) __p_branch_sample_type(buf, BUF_SIZE, val)
 #define p_read_format(val)     __p_read_format(buf, BUF_SIZE, val)
 
 #define PRINT_ATTRn(_n, _f, _p)                                \
@@ -1299,17 +1328,19 @@ int perf_event_attr__fprintf(FILE *fp, struct perf_event_attr *attr,
        PRINT_ATTRf(comm_exec, p_unsigned);
        PRINT_ATTRf(use_clockid, p_unsigned);
        PRINT_ATTRf(context_switch, p_unsigned);
+       PRINT_ATTRf(write_backward, p_unsigned);
 
        PRINT_ATTRn("{ wakeup_events, wakeup_watermark }", wakeup_events, p_unsigned);
        PRINT_ATTRf(bp_type, p_unsigned);
        PRINT_ATTRn("{ bp_addr, config1 }", bp_addr, p_hex);
        PRINT_ATTRn("{ bp_len, config2 }", bp_len, p_hex);
-       PRINT_ATTRf(branch_sample_type, p_unsigned);
+       PRINT_ATTRf(branch_sample_type, p_branch_sample_type);
        PRINT_ATTRf(sample_regs_user, p_hex);
        PRINT_ATTRf(sample_stack_user, p_unsigned);
        PRINT_ATTRf(clockid, p_signed);
        PRINT_ATTRf(sample_regs_intr, p_hex);
        PRINT_ATTRf(aux_watermark, p_unsigned);
+       PRINT_ATTRf(sample_max_stack, p_unsigned);
 
        return ret;
 }
@@ -1358,6 +1389,11 @@ fallback_missing_features:
        if (perf_missing_features.lbr_flags)
                evsel->attr.branch_sample_type &= ~(PERF_SAMPLE_BRANCH_NO_FLAGS |
                                     PERF_SAMPLE_BRANCH_NO_CYCLES);
+       if (perf_missing_features.write_backward) {
+               if (evsel->overwrite)
+                       return -EINVAL;
+               evsel->attr.write_backward = false;
+       }
 retry_sample_id:
        if (perf_missing_features.sample_id_all)
                evsel->attr.sample_id_all = 0;
@@ -1457,7 +1493,10 @@ try_fallback:
         * Must probe features in the order they were added to the
         * perf_event_attr interface.
         */
-       if (!perf_missing_features.clockid_wrong && evsel->attr.use_clockid) {
+       if (!perf_missing_features.write_backward && evsel->attr.write_backward) {
+               perf_missing_features.write_backward = true;
+               goto fallback_missing_features;
+       } else if (!perf_missing_features.clockid_wrong && evsel->attr.use_clockid) {
                perf_missing_features.clockid_wrong = true;
                goto fallback_missing_features;
        } else if (!perf_missing_features.clockid && evsel->attr.use_clockid) {
@@ -1483,7 +1522,6 @@ try_fallback:
                perf_missing_features.lbr_flags = true;
                goto fallback_missing_features;
        }
-
 out_close:
        do {
                while (--thread >= 0) {
@@ -2208,17 +2246,11 @@ void *perf_evsel__rawptr(struct perf_evsel *evsel, struct perf_sample *sample,
        return sample->raw_data + offset;
 }
 
-u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample,
-                      const char *name)
+u64 format_field__intval(struct format_field *field, struct perf_sample *sample,
+                        bool needs_swap)
 {
-       struct format_field *field = perf_evsel__field(evsel, name);
-       void *ptr;
        u64 value;
-
-       if (!field)
-               return 0;
-
-       ptr = sample->raw_data + field->offset;
+       void *ptr = sample->raw_data + field->offset;
 
        switch (field->size) {
        case 1:
@@ -2236,7 +2268,7 @@ u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample,
                return 0;
        }
 
-       if (!evsel->needs_swap)
+       if (!needs_swap)
                return value;
 
        switch (field->size) {
@@ -2253,93 +2285,15 @@ u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample,
        return 0;
 }
 
-static int comma_fprintf(FILE *fp, bool *first, const char *fmt, ...)
-{
-       va_list args;
-       int ret = 0;
-
-       if (!*first) {
-               ret += fprintf(fp, ",");
-       } else {
-               ret += fprintf(fp, ":");
-               *first = false;
-       }
-
-       va_start(args, fmt);
-       ret += vfprintf(fp, fmt, args);
-       va_end(args);
-       return ret;
-}
-
-static int __print_attr__fprintf(FILE *fp, const char *name, const char *val, void *priv)
-{
-       return comma_fprintf(fp, (bool *)priv, " %s: %s", name, val);
-}
-
-int perf_evsel__fprintf(struct perf_evsel *evsel,
-                       struct perf_attr_details *details, FILE *fp)
+u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample,
+                      const char *name)
 {
-       bool first = true;
-       int printed = 0;
-
-       if (details->event_group) {
-               struct perf_evsel *pos;
-
-               if (!perf_evsel__is_group_leader(evsel))
-                       return 0;
-
-               if (evsel->nr_members > 1)
-                       printed += fprintf(fp, "%s{", evsel->group_name ?: "");
-
-               printed += fprintf(fp, "%s", perf_evsel__name(evsel));
-               for_each_group_member(pos, evsel)
-                       printed += fprintf(fp, ",%s", perf_evsel__name(pos));
-
-               if (evsel->nr_members > 1)
-                       printed += fprintf(fp, "}");
-               goto out;
-       }
-
-       printed += fprintf(fp, "%s", perf_evsel__name(evsel));
-
-       if (details->verbose) {
-               printed += perf_event_attr__fprintf(fp, &evsel->attr,
-                                                   __print_attr__fprintf, &first);
-       } else if (details->freq) {
-               const char *term = "sample_freq";
-
-               if (!evsel->attr.freq)
-                       term = "sample_period";
-
-               printed += comma_fprintf(fp, &first, " %s=%" PRIu64,
-                                        term, (u64)evsel->attr.sample_freq);
-       }
-
-       if (details->trace_fields) {
-               struct format_field *field;
-
-               if (evsel->attr.type != PERF_TYPE_TRACEPOINT) {
-                       printed += comma_fprintf(fp, &first, " (not a tracepoint)");
-                       goto out;
-               }
-
-               field = evsel->tp_format->format.fields;
-               if (field == NULL) {
-                       printed += comma_fprintf(fp, &first, " (no trace field)");
-                       goto out;
-               }
+       struct format_field *field = perf_evsel__field(evsel, name);
 
-               printed += comma_fprintf(fp, &first, " trace_fields: %s", field->name);
+       if (!field)
+               return 0;
 
-               field = field->next;
-               while (field) {
-                       printed += comma_fprintf(fp, &first, "%s", field->name);
-                       field = field->next;
-               }
-       }
-out:
-       fputc('\n', fp);
-       return ++printed;
+       return field ? format_field__intval(field, sample, evsel->needs_swap) : 0;
 }
 
 bool perf_evsel__fallback(struct perf_evsel *evsel, int err,
@@ -2416,12 +2370,23 @@ int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target,
                         "Probably the maximum number of open file descriptors has been reached.\n"
                         "Hint: Try again after reducing the number of events.\n"
                         "Hint: Try increasing the limit with 'ulimit -n <limit>'");
+       case ENOMEM:
+               if ((evsel->attr.sample_type & PERF_SAMPLE_CALLCHAIN) != 0 &&
+                   access("/proc/sys/kernel/perf_event_max_stack", F_OK) == 0)
+                       return scnprintf(msg, size,
+                                        "Not enough memory to setup event with callchain.\n"
+                                        "Hint: Try tweaking /proc/sys/kernel/perf_event_max_stack\n"
+                                        "Hint: Current value: %d", sysctl_perf_event_max_stack);
+               break;
        case ENODEV:
                if (target->cpu_list)
                        return scnprintf(msg, size, "%s",
-        "No such device - did you specify an out-of-range profile CPU?\n");
+        "No such device - did you specify an out-of-range profile CPU?");
                break;
        case EOPNOTSUPP:
+               if (evsel->attr.sample_period != 0)
+                       return scnprintf(msg, size, "%s",
+       "PMU Hardware doesn't support sampling/overflow-interrupts.");
                if (evsel->attr.precise_ip)
                        return scnprintf(msg, size, "%s",
        "\'precise\' request may not be supported. Try removing 'p' modifier.");
@@ -2439,6 +2404,8 @@ int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target,
        "We found oprofile daemon running, please stop it and try again.");
                break;
        case EINVAL:
+               if (evsel->overwrite && perf_missing_features.write_backward)
+                       return scnprintf(msg, size, "Reading from overwrite event is not supported by this kernel.");
                if (perf_missing_features.clockid)
                        return scnprintf(msg, size, "clockid feature not supported.");
                if (perf_missing_features.clockid_wrong)
@@ -2451,7 +2418,7 @@ int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target,
        return scnprintf(msg, size,
        "The sys_perf_event_open() syscall returned with %d (%s) for event (%s).\n"
        "/bin/dmesg may provide additional information.\n"
-       "No CONFIG_PERF_EVENTS=y kernel support configured?\n",
+       "No CONFIG_PERF_EVENTS=y kernel support configured?",
                         err, strerror_r(err, sbuf, sizeof(sbuf)),
                         perf_evsel__name(evsel));
 }
This page took 0.041152 seconds and 5 git commands to generate.