Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c2b8d8c5 authored by Ingo Molnar's avatar Ingo Molnar
Browse files

Merge tag 'perf-core-for-mingo-2' of...

Merge tag 'perf-core-for-mingo-2' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux

 into perf/core

Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo:

New features:

  - Add API to set values of map entries in a BPF object, be it
    individual map slots or ranges (Wang Nan)

  - Introduce support for the 'bpf-output' event (Wang Nan)

  - Add glue to read perf events in a BPF program (Wang Nan)

User visible changes:

  - Don't stop PMU parsing on alias parse error, allowing the
    addition of new sysfs PMU files without breaking old tools (Andi Kleen)

  - Implement '%' operation in libtraceevent (Daniel Bristot de Oliveira)

  - Allow specifying events via -e in 'perf mem record', also listing what events
    can be specified via 'perf mem record -e list' (Jiri Olsa)

  - Improve support to 'data_src', 'weight' and 'addr' fields in
    'perf script' (Jiri Olsa)

Infrastructure changes:

  - Export cacheline routines (Jiri Olsa)

  - Remove strbuf_{remove,splice}(), dead code (Arnaldo Carvalho de Melo)

Fixes:

  - Sort key fixes: Alignment for srcline, file, trace; fix
    segfault for dynamic, trace events related sort keys (Namyung Kim)

Build fixes:

  - Remove duplicate typedef config_term_func_t definition,
    fixing the build on older systems (Arnaldo Carvalho de Melo)

Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parents 91e48b7d bea24006
Loading
Loading
Loading
Loading
+4 −0
Original line number Original line Diff line number Diff line
@@ -1951,6 +1951,7 @@ process_op(struct event_format *event, struct print_arg *arg, char **tok)
		   strcmp(token, "*") == 0 ||
		   strcmp(token, "*") == 0 ||
		   strcmp(token, "^") == 0 ||
		   strcmp(token, "^") == 0 ||
		   strcmp(token, "/") == 0 ||
		   strcmp(token, "/") == 0 ||
		   strcmp(token, "%") == 0 ||
		   strcmp(token, "<") == 0 ||
		   strcmp(token, "<") == 0 ||
		   strcmp(token, ">") == 0 ||
		   strcmp(token, ">") == 0 ||
		   strcmp(token, "<=") == 0 ||
		   strcmp(token, "<=") == 0 ||
@@ -3689,6 +3690,9 @@ eval_num_arg(void *data, int size, struct event_format *event, struct print_arg
		case '/':
		case '/':
			val = left / right;
			val = left / right;
			break;
			break;
		case '%':
			val = left % right;
			break;
		case '*':
		case '*':
			val = left * right;
			val = left * right;
			break;
			break;
+1 −2
Original line number Original line Diff line number Diff line
@@ -86,8 +86,7 @@ static int check_emacsclient_version(void)
		return -1;
		return -1;
	}
	}


	strbuf_remove(&buffer, 0, strlen("emacsclient"));
	version = atoi(buffer.buf + strlen("emacsclient"));
	version = atoi(buffer.buf);


	if (version < 22) {
	if (version < 22) {
		fprintf(stderr,
		fprintf(stderr,
+65 −9
Original line number Original line Diff line number Diff line
@@ -6,6 +6,8 @@
#include "util/tool.h"
#include "util/tool.h"
#include "util/session.h"
#include "util/session.h"
#include "util/data.h"
#include "util/data.h"
#include "util/mem-events.h"
#include "util/debug.h"


#define MEM_OPERATION_LOAD	0x1
#define MEM_OPERATION_LOAD	0x1
#define MEM_OPERATION_STORE	0x2
#define MEM_OPERATION_STORE	0x2
@@ -21,11 +23,55 @@ struct perf_mem {
	DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
	DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
};
};


static int parse_record_events(const struct option *opt,
			       const char *str, int unset __maybe_unused)
{
	struct perf_mem *mem = *(struct perf_mem **)opt->value;
	int j;

	if (strcmp(str, "list")) {
		if (!perf_mem_events__parse(str)) {
			mem->operation = 0;
			return 0;
		}
		exit(-1);
	}

	for (j = 0; j < PERF_MEM_EVENTS__MAX; j++) {
		struct perf_mem_event *e = &perf_mem_events[j];

		fprintf(stderr, "%-20s%s",
			e->tag, verbose ? "" : "\n");
		if (verbose)
			fprintf(stderr, " [%s]\n", e->name);
	}
	exit(0);
}

static const char * const __usage[] = {
	"perf mem record [<options>] [<command>]",
	"perf mem record [<options>] -- <command> [<options>]",
	NULL
};

static const char * const *record_mem_usage = __usage;

static int __cmd_record(int argc, const char **argv, struct perf_mem *mem)
static int __cmd_record(int argc, const char **argv, struct perf_mem *mem)
{
{
	int rec_argc, i = 0, j;
	int rec_argc, i = 0, j;
	const char **rec_argv;
	const char **rec_argv;
	int ret;
	int ret;
	struct option options[] = {
	OPT_CALLBACK('e', "event", &mem, "event",
		     "event selector. use 'perf mem record -e list' to list available events",
		     parse_record_events),
	OPT_INCR('v', "verbose", &verbose,
		 "be more verbose (show counter open errors, etc)"),
	OPT_END()
	};

	argc = parse_options(argc, argv, options, record_mem_usage,
			     PARSE_OPT_STOP_AT_NON_OPTION);


	rec_argc = argc + 7; /* max number of arguments */
	rec_argc = argc + 7; /* max number of arguments */
	rec_argv = calloc(rec_argc + 1, sizeof(char *));
	rec_argv = calloc(rec_argc + 1, sizeof(char *));
@@ -35,23 +81,34 @@ static int __cmd_record(int argc, const char **argv, struct perf_mem *mem)
	rec_argv[i++] = "record";
	rec_argv[i++] = "record";


	if (mem->operation & MEM_OPERATION_LOAD)
	if (mem->operation & MEM_OPERATION_LOAD)
		perf_mem_events[PERF_MEM_EVENTS__LOAD].record = true;

	if (perf_mem_events[PERF_MEM_EVENTS__LOAD].record)
		rec_argv[i++] = "-W";
		rec_argv[i++] = "-W";


	rec_argv[i++] = "-d";
	rec_argv[i++] = "-d";


	if (mem->operation & MEM_OPERATION_LOAD) {
	for (j = 0; j < PERF_MEM_EVENTS__MAX; j++) {
		rec_argv[i++] = "-e";
		if (!perf_mem_events[j].record)
		rec_argv[i++] = "cpu/mem-loads/pp";
			continue;
	}


	if (mem->operation & MEM_OPERATION_STORE) {
		rec_argv[i++] = "-e";
		rec_argv[i++] = "-e";
		rec_argv[i++] = "cpu/mem-stores/pp";
		rec_argv[i++] = perf_mem_events[j].name;
	}
	};


	for (j = 1; j < argc; j++, i++)
	for (j = 0; j < argc; j++, i++)
		rec_argv[i] = argv[j];
		rec_argv[i] = argv[j];


	if (verbose > 0) {
		pr_debug("calling: record ");

		while (rec_argv[j]) {
			pr_debug("%s ", rec_argv[j]);
			j++;
		}
		pr_debug("\n");
	}

	ret = cmd_record(i, rec_argv, NULL);
	ret = cmd_record(i, rec_argv, NULL);
	free(rec_argv);
	free(rec_argv);
	return ret;
	return ret;
@@ -298,7 +355,6 @@ int cmd_mem(int argc, const char **argv, const char *prefix __maybe_unused)
		NULL
		NULL
	};
	};



	argc = parse_options_subcommand(argc, argv, mem_options, mem_subcommands,
	argc = parse_options_subcommand(argc, argv, mem_options, mem_subcommands,
					mem_usage, PARSE_OPT_STOP_AT_NON_OPTION);
					mem_usage, PARSE_OPT_STOP_AT_NON_OPTION);


+11 −0
Original line number Original line Diff line number Diff line
@@ -32,6 +32,7 @@
#include "util/parse-branch-options.h"
#include "util/parse-branch-options.h"
#include "util/parse-regs-options.h"
#include "util/parse-regs-options.h"
#include "util/llvm-utils.h"
#include "util/llvm-utils.h"
#include "util/bpf-loader.h"


#include <unistd.h>
#include <unistd.h>
#include <sched.h>
#include <sched.h>
@@ -536,6 +537,16 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
		goto out_child;
		goto out_child;
	}
	}


	err = bpf__apply_obj_config();
	if (err) {
		char errbuf[BUFSIZ];

		bpf__strerror_apply_obj_config(err, errbuf, sizeof(errbuf));
		pr_err("ERROR: Apply config to BPF failed: %s\n",
			 errbuf);
		goto out_child;
	}

	/*
	/*
	 * Normally perf_session__new would do this, but it doesn't have the
	 * Normally perf_session__new would do this, but it doesn't have the
	 * evlist.
	 * evlist.
+22 −1
Original line number Original line Diff line number Diff line
@@ -58,6 +58,8 @@ enum perf_output_field {
	PERF_OUTPUT_IREGS	    = 1U << 14,
	PERF_OUTPUT_IREGS	    = 1U << 14,
	PERF_OUTPUT_BRSTACK	    = 1U << 15,
	PERF_OUTPUT_BRSTACK	    = 1U << 15,
	PERF_OUTPUT_BRSTACKSYM	    = 1U << 16,
	PERF_OUTPUT_BRSTACKSYM	    = 1U << 16,
	PERF_OUTPUT_DATA_SRC	    = 1U << 17,
	PERF_OUTPUT_WEIGHT	    = 1U << 18,
};
};


struct output_option {
struct output_option {
@@ -81,6 +83,8 @@ struct output_option {
	{.str = "iregs", .field = PERF_OUTPUT_IREGS},
	{.str = "iregs", .field = PERF_OUTPUT_IREGS},
	{.str = "brstack", .field = PERF_OUTPUT_BRSTACK},
	{.str = "brstack", .field = PERF_OUTPUT_BRSTACK},
	{.str = "brstacksym", .field = PERF_OUTPUT_BRSTACKSYM},
	{.str = "brstacksym", .field = PERF_OUTPUT_BRSTACKSYM},
	{.str = "data_src", .field = PERF_OUTPUT_DATA_SRC},
	{.str = "weight",   .field = PERF_OUTPUT_WEIGHT},
};
};


/* default set to maintain compatibility with current format */
/* default set to maintain compatibility with current format */
@@ -131,7 +135,8 @@ static struct {
			      PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
			      PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
			      PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
			      PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
			      PERF_OUTPUT_SYM | PERF_OUTPUT_DSO |
			      PERF_OUTPUT_SYM | PERF_OUTPUT_DSO |
			      PERF_OUTPUT_PERIOD,
			      PERF_OUTPUT_PERIOD |  PERF_OUTPUT_ADDR |
			      PERF_OUTPUT_DATA_SRC | PERF_OUTPUT_WEIGHT,


		.invalid_fields = PERF_OUTPUT_TRACE,
		.invalid_fields = PERF_OUTPUT_TRACE,
	},
	},
@@ -242,6 +247,16 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
					   PERF_OUTPUT_ADDR, allow_user_set))
					   PERF_OUTPUT_ADDR, allow_user_set))
		return -EINVAL;
		return -EINVAL;


	if (PRINT_FIELD(DATA_SRC) &&
		perf_evsel__check_stype(evsel, PERF_SAMPLE_DATA_SRC, "DATA_SRC",
					PERF_OUTPUT_DATA_SRC))
		return -EINVAL;

	if (PRINT_FIELD(WEIGHT) &&
		perf_evsel__check_stype(evsel, PERF_SAMPLE_WEIGHT, "WEIGHT",
					PERF_OUTPUT_WEIGHT))
		return -EINVAL;

	if (PRINT_FIELD(SYM) && !PRINT_FIELD(IP) && !PRINT_FIELD(ADDR)) {
	if (PRINT_FIELD(SYM) && !PRINT_FIELD(IP) && !PRINT_FIELD(ADDR)) {
		pr_err("Display of symbols requested but neither sample IP nor "
		pr_err("Display of symbols requested but neither sample IP nor "
			   "sample address\nis selected. Hence, no addresses to convert "
			   "sample address\nis selected. Hence, no addresses to convert "
@@ -673,6 +688,12 @@ static void process_event(struct perf_script *script, union perf_event *event,
	if (PRINT_FIELD(ADDR))
	if (PRINT_FIELD(ADDR))
		print_sample_addr(event, sample, thread, attr);
		print_sample_addr(event, sample, thread, attr);


	if (PRINT_FIELD(DATA_SRC))
		printf("%16" PRIx64, sample->data_src);

	if (PRINT_FIELD(WEIGHT))
		printf("%16" PRIu64, sample->weight);

	if (PRINT_FIELD(IP)) {
	if (PRINT_FIELD(IP)) {
		if (!symbol_conf.use_callchain)
		if (!symbol_conf.use_callchain)
			printf(" ");
			printf(" ");
Loading