Merge branch 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull perf updates from Ingo Molnar: "Bigger kernel side changes: - Add backwards writing capability to the perf ring-buffer code, which is preparation for future advanced features like robust 'overwrite support' and snapshot mode. (Wang Nan) - Add pause and resume ioctls for the perf ringbuffer (Wang Nan) - x86 Intel cstate code cleanups and reorgnization (Thomas Gleixner) - x86 Intel uncore and CPU PMU driver updates (Kan Liang, Peter Zijlstra) - x86 AUX (Intel PT) related enhancements and updates (Alexander Shishkin) - x86 MSR PMU driver enhancements and updates (Huang Rui) - ... and lots of other changes spread out over 40+ commits. Biggest tooling side changes: - 'perf trace' features and enhancements. (Arnaldo Carvalho de Melo) - BPF tooling updates (Wang Nan) - 'perf sched' updates (Jiri Olsa) - 'perf probe' updates (Masami Hiramatsu) - ... plus 200+ other enhancements, fixes and cleanups to tools/ The merge commits, the shortlog and the changelogs contain a lot more details" * 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (249 commits) perf/core: Disable the event on a truncated AUX record perf/x86/intel/pt: Generate PMI in the STOP region as well perf buildid-cache: Use lsdir() for looking up buildid caches perf symbols: Use lsdir() for the search in kcore cache directory perf tools: Use SBUILD_ID_SIZE where applicable perf tools: Fix lsdir to set errno correctly perf trace: Move seccomp args beautifiers to tools/perf/trace/beauty/ perf trace: Move flock op beautifier to tools/perf/trace/beauty/ perf build: Add build-test for debug-frame on arm/arm64 perf build: Add build-test for libunwind cross-platforms support perf script: Fix export of callchains with recursion in db-export perf script: Fix callchain addresses in db-export perf script: Fix symbol insertion behavior in db-export perf symbols: Add dso__insert_symbol function perf scripting python: Use Py_FatalError instead of die() perf tools: Remove xrealloc and ALLOC_GROW perf help: Do not use ALLOC_GROW in add_cmd_list perf pmu: Make pmu_formats_string to check return value of strbuf perf header: Make topology checkers to check return value of strbuf perf tools: Make alias handler to check return value of strbuf ...
This commit is contained in:
@@ -226,7 +226,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,10 +562,9 @@ 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;
|
||||
@@ -704,7 +704,7 @@ static void apply_config_terms(struct perf_evsel *evsel,
|
||||
|
||||
/* set perf-event callgraph */
|
||||
if (param.enabled)
|
||||
perf_evsel__config_callgraph(evsel, opts, ¶m);
|
||||
perf_evsel__config_callchain(evsel, opts, ¶m);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -736,7 +736,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 +812,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;
|
||||
@@ -1230,6 +1231,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 +1264,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,12 +1316,13 @@ 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);
|
||||
@@ -2253,95 +2271,6 @@ 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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
printed += comma_fprintf(fp, &first, " trace_fields: %s", field->name);
|
||||
|
||||
field = field->next;
|
||||
while (field) {
|
||||
printed += comma_fprintf(fp, &first, "%s", field->name);
|
||||
field = field->next;
|
||||
}
|
||||
}
|
||||
out:
|
||||
fputc('\n', fp);
|
||||
return ++printed;
|
||||
}
|
||||
|
||||
bool perf_evsel__fallback(struct perf_evsel *evsel, int err,
|
||||
char *msg, size_t msgsize)
|
||||
{
|
||||
@@ -2416,10 +2345,18 @@ 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.precise_ip)
|
||||
@@ -2451,7 +2388,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));
|
||||
}
|
||||
|
Reference in New Issue
Block a user