Commit 7f06d0aa authored by Ingo Molnar's avatar Ingo Molnar
Browse files

Merge tag 'perf-core-for-mingo-5.4-20190729' of...

Merge tag 'perf-core-for-mingo-5.4-20190729' 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:

perf trace:

  Arnaldo Carvalho de Melo:

  - Use BPF_MAP_TYPE_PROG_ARRAY + bpf_tail_call() for augmenting raw syscalls,
    i.e. copy pointers passed to/from userspace. The use of a table per syscall
    to tell the BPF program what to copy made the raw_syscalls:sys_enter/exit
    programs a bit complex, the scratch space would have to be bigger to allow
    for checking all args to see which ones were a pathname, so use a PROG_ARRAY
    map instead, test it with syscalls that receive multiple pathnames at
    different registers (rename, renameat, etc).

  - Beautify various syscalls using this new infrastructure, and also add code
    that looks for syscalls with BPF augmenters, such as "open", and then reuse
    it with syscalls not yet having a specific augmenter, but that copies the
    same argument with the same type, say "statfs" can initially reuse "open",
    beautifier, as both have as its first arg a "const char *".

  - Do not using fd->pathname beautifier when the 'close' syscall isn't enabled,
    as we can't invalidate that mapping.

core:

  Jiri Olsa:

  - Introduce tools/perf/lib/, that eventually will move to tools/lib/perf/, to
    allow other tools to use the abstractions and code perf uses to set up
    the perf ring buffer and set up the many possible combinations in allowed
    by the kernel, starting with 'struct perf_evsel' and 'struct perf_evlist'.

perf vendor events:

  Michael Petlan:

  - Add missing event description to power9 event definitions.

Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parents b3c303be 123a039d
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -277,6 +277,7 @@ ifeq ($(DEBUG),0)
  endif
endif

INC_FLAGS += -I$(src-perf)/lib/include
INC_FLAGS += -I$(src-perf)/util/include
INC_FLAGS += -I$(src-perf)/arch/$(SRCARCH)/include
INC_FLAGS += -I$(srctree)/tools/include/uapi
+17 −14
Original line number Diff line number Diff line
@@ -224,6 +224,7 @@ LIB_DIR = $(srctree)/tools/lib/api/
TRACE_EVENT_DIR = $(srctree)/tools/lib/traceevent/
BPF_DIR         = $(srctree)/tools/lib/bpf/
SUBCMD_DIR      = $(srctree)/tools/lib/subcmd/
LIBPERF_DIR     = $(srctree)/tools/perf/lib/

# Set FEATURE_TESTS to 'all' so all possible feature checkers are executed.
# Without this setting the output feature dump file misses some features, for
@@ -272,6 +273,7 @@ ifneq ($(OUTPUT),)
  TE_PATH=$(OUTPUT)
  BPF_PATH=$(OUTPUT)
  SUBCMD_PATH=$(OUTPUT)
  LIBPERF_PATH=$(OUTPUT)
ifneq ($(subdir),)
  API_PATH=$(OUTPUT)/../lib/api/
else
@@ -282,6 +284,7 @@ else
  API_PATH=$(LIB_DIR)
  BPF_PATH=$(BPF_DIR)
  SUBCMD_PATH=$(SUBCMD_DIR)
  LIBPERF_PATH=$(LIBPERF_DIR)
endif

LIBTRACEEVENT = $(TE_PATH)libtraceevent.a
@@ -303,6 +306,9 @@ LIBBPF = $(BPF_PATH)libbpf.a

LIBSUBCMD = $(SUBCMD_PATH)libsubcmd.a

LIBPERF = $(LIBPERF_PATH)libperf.a
export LIBPERF

# python extension build directories
PYTHON_EXTBUILD     := $(OUTPUT)python_ext_build/
PYTHON_EXTBUILD_LIB := $(PYTHON_EXTBUILD)lib/
@@ -348,9 +354,7 @@ endif

export PERL_PATH

LIBPERF_A=$(OUTPUT)libperf.a

PERFLIBS = $(LIBAPI) $(LIBTRACEEVENT) $(LIBSUBCMD)
PERFLIBS = $(LIBAPI) $(LIBTRACEEVENT) $(LIBSUBCMD) $(LIBPERF)
ifndef NO_LIBBPF
  PERFLIBS += $(LIBBPF)
endif
@@ -583,8 +587,6 @@ JEVENTS_IN := $(OUTPUT)pmu-events/jevents-in.o

PMU_EVENTS_IN := $(OUTPUT)pmu-events/pmu-events-in.o

LIBPERF_IN := $(OUTPUT)libperf-in.o

export JEVENTS

build := -f $(srctree)/tools/build/Makefile.build dir=. obj
@@ -601,12 +603,9 @@ $(JEVENTS): $(JEVENTS_IN)
$(PMU_EVENTS_IN): $(JEVENTS) FORCE
	$(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=pmu-events obj=pmu-events

$(LIBPERF_IN): prepare FORCE
	$(Q)$(MAKE) $(build)=libperf

$(OUTPUT)perf: $(PERFLIBS) $(PERF_IN) $(PMU_EVENTS_IN) $(LIBPERF_IN) $(LIBTRACEEVENT_DYNAMIC_LIST)
$(OUTPUT)perf: $(PERFLIBS) $(PERF_IN) $(PMU_EVENTS_IN) $(LIBTRACEEVENT_DYNAMIC_LIST)
	$(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $(LIBTRACEEVENT_DYNAMIC_LIST_LDFLAGS) \
		$(PERF_IN) $(PMU_EVENTS_IN) $(LIBPERF_IN) $(LIBS) -o $@
		$(PERF_IN) $(PMU_EVENTS_IN) $(LIBS) -o $@

$(GTK_IN): FORCE
	$(Q)$(MAKE) $(build)=gtk
@@ -727,9 +726,6 @@ endif

$(patsubst perf-%,%.o,$(PROGRAMS)): $(wildcard */*.h)

$(LIBPERF_A): $(LIBPERF_IN)
	$(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(LIBPERF_IN) $(LIB_OBJS)

LIBTRACEEVENT_FLAGS += plugin_dir=$(plugindir_SQ) 'EXTRA_CFLAGS=$(EXTRA_CFLAGS)' 'LDFLAGS=$(LDFLAGS)'

$(LIBTRACEEVENT): FORCE
@@ -762,6 +758,13 @@ $(LIBBPF)-clean:
	$(call QUIET_CLEAN, libbpf)
	$(Q)$(MAKE) -C $(BPF_DIR) O=$(OUTPUT) clean >/dev/null

$(LIBPERF): FORCE
	$(Q)$(MAKE) -C $(LIBPERF_DIR) O=$(OUTPUT) $(OUTPUT)libperf.a

$(LIBPERF)-clean:
	$(call QUIET_CLEAN, libperf)
	$(Q)$(MAKE) -C $(LIBPERF_DIR) O=$(OUTPUT) clean >/dev/null

$(LIBSUBCMD): FORCE
	$(Q)$(MAKE) -C $(SUBCMD_DIR) O=$(OUTPUT) $(OUTPUT)libsubcmd.a

@@ -948,7 +951,7 @@ config-clean:
python-clean:
	$(python-clean)

clean:: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean $(LIBBPF)-clean $(LIBSUBCMD)-clean config-clean fixdep-clean python-clean
clean:: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean $(LIBBPF)-clean $(LIBSUBCMD)-clean $(LIBPERF)-clean config-clean fixdep-clean python-clean
	$(call QUIET_CLEAN, core-objs)  $(RM) $(LIBPERF_A) $(OUTPUT)perf-archive $(OUTPUT)perf-with-kcore $(LANG_BINDINGS)
	$(Q)find $(if $(OUTPUT),$(OUTPUT),.) -name '*.o' -delete -o -name '\.*.cmd' -delete -o -name '\.*.d' -delete
	$(Q)$(RM) $(OUTPUT).config-detected
+4 −4
Original line number Diff line number Diff line
@@ -50,10 +50,10 @@ static struct perf_pmu **find_all_arm_spe_pmus(int *nr_spes, int *err)
}

struct auxtrace_record
*auxtrace_record__init(struct perf_evlist *evlist, int *err)
*auxtrace_record__init(struct evlist *evlist, int *err)
{
	struct perf_pmu	*cs_etm_pmu;
	struct perf_evsel *evsel;
	struct evsel *evsel;
	bool found_etm = false;
	bool found_spe = false;
	static struct perf_pmu **arm_spe_pmus = NULL;
@@ -70,14 +70,14 @@ struct auxtrace_record

	evlist__for_each_entry(evlist, evsel) {
		if (cs_etm_pmu &&
		    evsel->attr.type == cs_etm_pmu->type)
		    evsel->core.attr.type == cs_etm_pmu->type)
			found_etm = true;

		if (!nr_spes)
			continue;

		for (i = 0; i < nr_spes; i++) {
			if (evsel->attr.type == arm_spe_pmus[i]->type) {
			if (evsel->core.attr.type == arm_spe_pmus[i]->type) {
				found_spe = true;
				break;
			}
+41 −41
Original line number Diff line number Diff line
@@ -32,7 +32,7 @@
struct cs_etm_recording {
	struct auxtrace_record	itr;
	struct perf_pmu		*cs_etm_pmu;
	struct perf_evlist	*evlist;
	struct evlist		*evlist;
	int			wrapped_cnt;
	bool			*wrapped;
	bool			snapshot_mode;
@@ -55,7 +55,7 @@ static const char *metadata_etmv4_ro[CS_ETMV4_PRIV_MAX] = {
static bool cs_etm_is_etmv4(struct auxtrace_record *itr, int cpu);

static int cs_etm_set_context_id(struct auxtrace_record *itr,
				 struct perf_evsel *evsel, int cpu)
				 struct evsel *evsel, int cpu)
{
	struct cs_etm_recording *ptr;
	struct perf_pmu *cs_etm_pmu;
@@ -95,7 +95,7 @@ static int cs_etm_set_context_id(struct auxtrace_record *itr,
	}

	/* All good, let the kernel know */
	evsel->attr.config |= (1 << ETM_OPT_CTXTID);
	evsel->core.attr.config |= (1 << ETM_OPT_CTXTID);
	err = 0;

out:
@@ -104,7 +104,7 @@ out:
}

static int cs_etm_set_timestamp(struct auxtrace_record *itr,
				struct perf_evsel *evsel, int cpu)
				struct evsel *evsel, int cpu)
{
	struct cs_etm_recording *ptr;
	struct perf_pmu *cs_etm_pmu;
@@ -144,7 +144,7 @@ static int cs_etm_set_timestamp(struct auxtrace_record *itr,
	}

	/* All good, let the kernel know */
	evsel->attr.config |= (1 << ETM_OPT_TS);
	evsel->core.attr.config |= (1 << ETM_OPT_TS);
	err = 0;

out:
@@ -152,11 +152,11 @@ out:
}

static int cs_etm_set_option(struct auxtrace_record *itr,
			     struct perf_evsel *evsel, u32 option)
			     struct evsel *evsel, u32 option)
{
	int i, err = -EINVAL;
	struct cpu_map *event_cpus = evsel->evlist->cpus;
	struct cpu_map *online_cpus = cpu_map__new(NULL);
	struct perf_cpu_map *event_cpus = evsel->evlist->core.cpus;
	struct perf_cpu_map *online_cpus = perf_cpu_map__new(NULL);

	/* Set option of each CPU we have */
	for (i = 0; i < cpu__max_cpu(); i++) {
@@ -181,7 +181,7 @@ static int cs_etm_set_option(struct auxtrace_record *itr,

	err = 0;
out:
	cpu_map__put(online_cpus);
	perf_cpu_map__put(online_cpus);
	return err;
}

@@ -208,14 +208,14 @@ static int cs_etm_parse_snapshot_options(struct auxtrace_record *itr,
}

static int cs_etm_set_sink_attr(struct perf_pmu *pmu,
				struct perf_evsel *evsel)
				struct evsel *evsel)
{
	char msg[BUFSIZ], path[PATH_MAX], *sink;
	struct perf_evsel_config_term *term;
	int ret = -EINVAL;
	u32 hash;

	if (evsel->attr.config2 & GENMASK(31, 0))
	if (evsel->core.attr.config2 & GENMASK(31, 0))
		return 0;

	list_for_each_entry(term, &evsel->config_terms, list) {
@@ -233,7 +233,7 @@ static int cs_etm_set_sink_attr(struct perf_pmu *pmu,
			return ret;
		}

		evsel->attr.config2 |= hash;
		evsel->core.attr.config2 |= hash;
		return 0;
	}

@@ -245,15 +245,15 @@ static int cs_etm_set_sink_attr(struct perf_pmu *pmu,
}

static int cs_etm_recording_options(struct auxtrace_record *itr,
				    struct perf_evlist *evlist,
				    struct evlist *evlist,
				    struct record_opts *opts)
{
	int ret;
	struct cs_etm_recording *ptr =
				container_of(itr, struct cs_etm_recording, itr);
	struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu;
	struct perf_evsel *evsel, *cs_etm_evsel = NULL;
	struct cpu_map *cpus = evlist->cpus;
	struct evsel *evsel, *cs_etm_evsel = NULL;
	struct perf_cpu_map *cpus = evlist->core.cpus;
	bool privileged = (geteuid() == 0 || perf_event_paranoid() < 0);
	int err = 0;

@@ -264,14 +264,14 @@ static int cs_etm_recording_options(struct auxtrace_record *itr,
		opts->record_switch_events = true;

	evlist__for_each_entry(evlist, evsel) {
		if (evsel->attr.type == cs_etm_pmu->type) {
		if (evsel->core.attr.type == cs_etm_pmu->type) {
			if (cs_etm_evsel) {
				pr_err("There may be only one %s event\n",
				       CORESIGHT_ETM_PMU_NAME);
				return -EINVAL;
			}
			evsel->attr.freq = 0;
			evsel->attr.sample_period = 1;
			evsel->core.attr.freq = 0;
			evsel->core.attr.sample_period = 1;
			cs_etm_evsel = evsel;
			opts->full_auxtrace = true;
		}
@@ -407,7 +407,7 @@ static int cs_etm_recording_options(struct auxtrace_record *itr,

	/* Add dummy event to keep tracking */
	if (opts->full_auxtrace) {
		struct perf_evsel *tracking_evsel;
		struct evsel *tracking_evsel;

		err = parse_events(evlist, "dummy:u", NULL);
		if (err)
@@ -416,8 +416,8 @@ static int cs_etm_recording_options(struct auxtrace_record *itr,
		tracking_evsel = perf_evlist__last(evlist);
		perf_evlist__set_tracking_event(evlist, tracking_evsel);

		tracking_evsel->attr.freq = 0;
		tracking_evsel->attr.sample_period = 1;
		tracking_evsel->core.attr.freq = 0;
		tracking_evsel->core.attr.sample_period = 1;

		/* In per-cpu case, always need the time of mmap events etc */
		if (!cpu_map__empty(cpus))
@@ -434,11 +434,11 @@ static u64 cs_etm_get_config(struct auxtrace_record *itr)
	struct cs_etm_recording *ptr =
			container_of(itr, struct cs_etm_recording, itr);
	struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu;
	struct perf_evlist *evlist = ptr->evlist;
	struct perf_evsel *evsel;
	struct evlist *evlist = ptr->evlist;
	struct evsel *evsel;

	evlist__for_each_entry(evlist, evsel) {
		if (evsel->attr.type == cs_etm_pmu->type) {
		if (evsel->core.attr.type == cs_etm_pmu->type) {
			/*
			 * Variable perf_event_attr::config is assigned to
			 * ETMv3/PTM.  The bit fields have been made to match
@@ -447,7 +447,7 @@ static u64 cs_etm_get_config(struct auxtrace_record *itr)
			 * drivers/hwtracing/coresight/coresight-perf.c for
			 * details.
			 */
			config = evsel->attr.config;
			config = evsel->core.attr.config;
			break;
		}
	}
@@ -485,12 +485,12 @@ static u64 cs_etmv4_get_config(struct auxtrace_record *itr)

static size_t
cs_etm_info_priv_size(struct auxtrace_record *itr __maybe_unused,
		      struct perf_evlist *evlist __maybe_unused)
		      struct evlist *evlist __maybe_unused)
{
	int i;
	int etmv3 = 0, etmv4 = 0;
	struct cpu_map *event_cpus = evlist->cpus;
	struct cpu_map *online_cpus = cpu_map__new(NULL);
	struct perf_cpu_map *event_cpus = evlist->core.cpus;
	struct perf_cpu_map *online_cpus = perf_cpu_map__new(NULL);

	/* cpu map is not empty, we have specific CPUs to work with */
	if (!cpu_map__empty(event_cpus)) {
@@ -517,7 +517,7 @@ cs_etm_info_priv_size(struct auxtrace_record *itr __maybe_unused,
		}
	}

	cpu_map__put(online_cpus);
	perf_cpu_map__put(online_cpus);

	return (CS_ETM_HEADER_SIZE +
	       (etmv4 * CS_ETMV4_PRIV_SIZE) +
@@ -635,9 +635,9 @@ static int cs_etm_info_fill(struct auxtrace_record *itr,
	int i;
	u32 offset;
	u64 nr_cpu, type;
	struct cpu_map *cpu_map;
	struct cpu_map *event_cpus = session->evlist->cpus;
	struct cpu_map *online_cpus = cpu_map__new(NULL);
	struct perf_cpu_map *cpu_map;
	struct perf_cpu_map *event_cpus = session->evlist->core.cpus;
	struct perf_cpu_map *online_cpus = perf_cpu_map__new(NULL);
	struct cs_etm_recording *ptr =
			container_of(itr, struct cs_etm_recording, itr);
	struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu;
@@ -679,7 +679,7 @@ static int cs_etm_info_fill(struct auxtrace_record *itr,
		if (cpu_map__has(cpu_map, i))
			cs_etm_get_metadata(i, &offset, itr, info);

	cpu_map__put(online_cpus);
	perf_cpu_map__put(online_cpus);

	return 0;
}
@@ -817,11 +817,11 @@ static int cs_etm_snapshot_start(struct auxtrace_record *itr)
{
	struct cs_etm_recording *ptr =
			container_of(itr, struct cs_etm_recording, itr);
	struct perf_evsel *evsel;
	struct evsel *evsel;

	evlist__for_each_entry(ptr->evlist, evsel) {
		if (evsel->attr.type == ptr->cs_etm_pmu->type)
			return perf_evsel__disable(evsel);
		if (evsel->core.attr.type == ptr->cs_etm_pmu->type)
			return evsel__disable(evsel);
	}
	return -EINVAL;
}
@@ -830,11 +830,11 @@ static int cs_etm_snapshot_finish(struct auxtrace_record *itr)
{
	struct cs_etm_recording *ptr =
			container_of(itr, struct cs_etm_recording, itr);
	struct perf_evsel *evsel;
	struct evsel *evsel;

	evlist__for_each_entry(ptr->evlist, evsel) {
		if (evsel->attr.type == ptr->cs_etm_pmu->type)
			return perf_evsel__enable(evsel);
		if (evsel->core.attr.type == ptr->cs_etm_pmu->type)
			return evsel__enable(evsel);
	}
	return -EINVAL;
}
@@ -858,10 +858,10 @@ static int cs_etm_read_finish(struct auxtrace_record *itr, int idx)
{
	struct cs_etm_recording *ptr =
			container_of(itr, struct cs_etm_recording, itr);
	struct perf_evsel *evsel;
	struct evsel *evsel;

	evlist__for_each_entry(ptr->evlist, evsel) {
		if (evsel->attr.type == ptr->cs_etm_pmu->type)
		if (evsel->core.attr.type == ptr->cs_etm_pmu->type)
			return perf_evlist__enable_event_idx(ptr->evlist,
							     evsel, idx);
	}
+12 −12
Original line number Diff line number Diff line
@@ -27,12 +27,12 @@
struct arm_spe_recording {
	struct auxtrace_record		itr;
	struct perf_pmu			*arm_spe_pmu;
	struct perf_evlist		*evlist;
	struct evlist		*evlist;
};

static size_t
arm_spe_info_priv_size(struct auxtrace_record *itr __maybe_unused,
		       struct perf_evlist *evlist __maybe_unused)
		       struct evlist *evlist __maybe_unused)
{
	return ARM_SPE_AUXTRACE_PRIV_SIZE;
}
@@ -59,27 +59,27 @@ static int arm_spe_info_fill(struct auxtrace_record *itr,
}

static int arm_spe_recording_options(struct auxtrace_record *itr,
				     struct perf_evlist *evlist,
				     struct evlist *evlist,
				     struct record_opts *opts)
{
	struct arm_spe_recording *sper =
			container_of(itr, struct arm_spe_recording, itr);
	struct perf_pmu *arm_spe_pmu = sper->arm_spe_pmu;
	struct perf_evsel *evsel, *arm_spe_evsel = NULL;
	struct evsel *evsel, *arm_spe_evsel = NULL;
	bool privileged = geteuid() == 0 || perf_event_paranoid() < 0;
	struct perf_evsel *tracking_evsel;
	struct evsel *tracking_evsel;
	int err;

	sper->evlist = evlist;

	evlist__for_each_entry(evlist, evsel) {
		if (evsel->attr.type == arm_spe_pmu->type) {
		if (evsel->core.attr.type == arm_spe_pmu->type) {
			if (arm_spe_evsel) {
				pr_err("There may be only one " ARM_SPE_PMU_NAME "x event\n");
				return -EINVAL;
			}
			evsel->attr.freq = 0;
			evsel->attr.sample_period = 1;
			evsel->core.attr.freq = 0;
			evsel->core.attr.sample_period = 1;
			arm_spe_evsel = evsel;
			opts->full_auxtrace = true;
		}
@@ -130,8 +130,8 @@ static int arm_spe_recording_options(struct auxtrace_record *itr,
	tracking_evsel = perf_evlist__last(evlist);
	perf_evlist__set_tracking_event(evlist, tracking_evsel);

	tracking_evsel->attr.freq = 0;
	tracking_evsel->attr.sample_period = 1;
	tracking_evsel->core.attr.freq = 0;
	tracking_evsel->core.attr.sample_period = 1;
	perf_evsel__set_sample_bit(tracking_evsel, TIME);
	perf_evsel__set_sample_bit(tracking_evsel, CPU);
	perf_evsel__reset_sample_bit(tracking_evsel, BRANCH_STACK);
@@ -160,10 +160,10 @@ static int arm_spe_read_finish(struct auxtrace_record *itr, int idx)
{
	struct arm_spe_recording *sper =
			container_of(itr, struct arm_spe_recording, itr);
	struct perf_evsel *evsel;
	struct evsel *evsel;

	evlist__for_each_entry(sper->evlist, evsel) {
		if (evsel->attr.type == sper->arm_spe_pmu->type)
		if (evsel->core.attr.type == sper->arm_spe_pmu->type)
			return perf_evlist__enable_event_idx(sper->evlist,
							     evsel, idx);
	}
Loading