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

Commit 1d039859 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull perf fixes from Ingo Molnar:
 "A number of PMU driver corner case fixes, a race fix, an event
  grouping fix, plus a bunch of tooling fixes/updates"

* 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (30 commits)
  perf/x86/intel: Fix spurious NMI on fixed counter
  perf/core: Fix exclusive events' grouping
  perf/x86/amd/uncore: Set the thread mask for F17h L3 PMCs
  perf/x86/amd/uncore: Do not set 'ThreadMask' and 'SliceMask' for non-L3 PMCs
  perf/core: Fix race between close() and fork()
  perf intel-pt: Fix potential NULL pointer dereference found by the smatch tool
  perf intel-bts: Fix potential NULL pointer dereference found by the smatch tool
  perf script: Assume native_arch for pipe mode
  perf scripts python: export-to-sqlite.py: Fix DROP VIEW power_events_view
  perf scripts python: export-to-postgresql.py: Fix DROP VIEW power_events_view
  perf hists browser: Fix potential NULL pointer dereference found by the smatch tool
  perf cs-etm: Fix potential NULL pointer dereference found by the smatch tool
  perf parse-events: Remove unused variable: error
  perf parse-events: Remove unused variable 'i'
  perf metricgroup: Add missing list_del_init() when flushing egroups list
  perf tools: Use list_del_init() more thorougly
  perf tools: Use zfree() where applicable
  tools lib: Adopt zalloc()/zfree() from tools/perf
  perf tools: Move get_current_dir_name() cond prototype out of util.h
  perf namespaces: Move the conditional setns() prototype to namespaces.h
  ...
parents 0c85ce13 e4557c1a
Loading
Loading
Loading
Loading
+11 −4
Original line number Diff line number Diff line
@@ -202,15 +202,22 @@ static int amd_uncore_event_init(struct perf_event *event)
	hwc->config = event->attr.config & AMD64_RAW_EVENT_MASK_NB;
	hwc->idx = -1;

	if (event->cpu < 0)
		return -EINVAL;

	/*
	 * SliceMask and ThreadMask need to be set for certain L3 events in
	 * Family 17h. For other events, the two fields do not affect the count.
	 */
	if (l3_mask)
		hwc->config |= (AMD64_L3_SLICE_MASK | AMD64_L3_THREAD_MASK);
	if (l3_mask && is_llc_event(event)) {
		int thread = 2 * (cpu_data(event->cpu).cpu_core_id % 4);

	if (event->cpu < 0)
		return -EINVAL;
		if (smp_num_siblings > 1)
			thread += cpu_data(event->cpu).apicid & 1;

		hwc->config |= (1ULL << (AMD64_L3_THREAD_SHIFT + thread) &
				AMD64_L3_THREAD_MASK) | AMD64_L3_SLICE_MASK;
	}

	uncore = event_to_amd_uncore(event);
	if (!uncore)
+3 −5
Original line number Diff line number Diff line
@@ -2161,11 +2161,9 @@ static void intel_pmu_disable_event(struct perf_event *event)
	cpuc->intel_ctrl_host_mask &= ~(1ull << hwc->idx);
	cpuc->intel_cp_status &= ~(1ull << hwc->idx);

	if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL)) {
	if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL))
		intel_pmu_disable_fixed(hwc);
		return;
	}

	else
		x86_pmu_disable_event(event);

	/*
+5 −0
Original line number Diff line number Diff line
@@ -1055,6 +1055,11 @@ static inline int in_software_context(struct perf_event *event)
	return event->ctx->pmu->task_ctx_nr == perf_sw_context;
}

static inline int is_exclusive_pmu(struct pmu *pmu)
{
	return pmu->capabilities & PERF_PMU_CAP_EXCLUSIVE;
}

extern struct static_key perf_swevent_enabled[PERF_COUNT_SW_MAX];

extern void ___perf_sw_event(u32, u64, struct pt_regs *, u64);
+63 −20
Original line number Diff line number Diff line
@@ -2553,6 +2553,9 @@ static int __perf_install_in_context(void *info)
	return ret;
}

static bool exclusive_event_installable(struct perf_event *event,
					struct perf_event_context *ctx);

/*
 * Attach a performance event to a context.
 *
@@ -2567,6 +2570,8 @@ perf_install_in_context(struct perf_event_context *ctx,

	lockdep_assert_held(&ctx->mutex);

	WARN_ON_ONCE(!exclusive_event_installable(event, ctx));

	if (event->cpu != -1)
		event->cpu = cpu;

@@ -4360,7 +4365,7 @@ static int exclusive_event_init(struct perf_event *event)
{
	struct pmu *pmu = event->pmu;

	if (!(pmu->capabilities & PERF_PMU_CAP_EXCLUSIVE))
	if (!is_exclusive_pmu(pmu))
		return 0;

	/*
@@ -4391,7 +4396,7 @@ static void exclusive_event_destroy(struct perf_event *event)
{
	struct pmu *pmu = event->pmu;

	if (!(pmu->capabilities & PERF_PMU_CAP_EXCLUSIVE))
	if (!is_exclusive_pmu(pmu))
		return;

	/* see comment in exclusive_event_init() */
@@ -4411,14 +4416,15 @@ static bool exclusive_event_match(struct perf_event *e1, struct perf_event *e2)
	return false;
}

/* Called under the same ctx::mutex as perf_install_in_context() */
static bool exclusive_event_installable(struct perf_event *event,
					struct perf_event_context *ctx)
{
	struct perf_event *iter_event;
	struct pmu *pmu = event->pmu;

	if (!(pmu->capabilities & PERF_PMU_CAP_EXCLUSIVE))
	lockdep_assert_held(&ctx->mutex);

	if (!is_exclusive_pmu(pmu))
		return true;

	list_for_each_entry(iter_event, &ctx->event_list, event_entry) {
@@ -4465,12 +4471,20 @@ static void _free_event(struct perf_event *event)
	if (event->destroy)
		event->destroy(event);

	if (event->ctx)
		put_ctx(event->ctx);

	/*
	 * Must be after ->destroy(), due to uprobe_perf_close() using
	 * hw.target.
	 */
	if (event->hw.target)
		put_task_struct(event->hw.target);

	/*
	 * perf_event_free_task() relies on put_ctx() being 'last', in particular
	 * all task references must be cleaned up.
	 */
	if (event->ctx)
		put_ctx(event->ctx);

	exclusive_event_destroy(event);
	module_put(event->pmu->module);

@@ -4650,8 +4664,17 @@ int perf_event_release_kernel(struct perf_event *event)
	mutex_unlock(&event->child_mutex);

	list_for_each_entry_safe(child, tmp, &free_list, child_list) {
		void *var = &child->ctx->refcount;

		list_del(&child->child_list);
		free_event(child);

		/*
		 * Wake any perf_event_free_task() waiting for this event to be
		 * freed.
		 */
		smp_mb(); /* pairs with wait_var_event() */
		wake_up_var(var);
	}

no_ctx:
@@ -10930,11 +10953,6 @@ SYSCALL_DEFINE5(perf_event_open,
		goto err_alloc;
	}

	if ((pmu->capabilities & PERF_PMU_CAP_EXCLUSIVE) && group_leader) {
		err = -EBUSY;
		goto err_context;
	}

	/*
	 * Look up the group leader (we will attach this event to it):
	 */
@@ -11022,6 +11040,18 @@ SYSCALL_DEFINE5(perf_event_open,
				move_group = 0;
			}
		}

		/*
		 * Failure to create exclusive events returns -EBUSY.
		 */
		err = -EBUSY;
		if (!exclusive_event_installable(group_leader, ctx))
			goto err_locked;

		for_each_sibling_event(sibling, group_leader) {
			if (!exclusive_event_installable(sibling, ctx))
				goto err_locked;
		}
	} else {
		mutex_lock(&ctx->mutex);
	}
@@ -11058,9 +11088,6 @@ SYSCALL_DEFINE5(perf_event_open,
	 * because we need to serialize with concurrent event creation.
	 */
	if (!exclusive_event_installable(event, ctx)) {
		/* exclusive and group stuff are assumed mutually exclusive */
		WARN_ON_ONCE(move_group);

		err = -EBUSY;
		goto err_locked;
	}
@@ -11527,11 +11554,11 @@ static void perf_free_event(struct perf_event *event,
}

/*
 * Free an unexposed, unused context as created by inheritance by
 * perf_event_init_task below, used by fork() in case of fail.
 * Free a context as created by inheritance by perf_event_init_task() below,
 * used by fork() in case of fail.
 *
 * Not all locks are strictly required, but take them anyway to be nice and
 * help out with the lockdep assertions.
 * Even though the task has never lived, the context and events have been
 * exposed through the child_list, so we must take care tearing it all down.
 */
void perf_event_free_task(struct task_struct *task)
{
@@ -11561,7 +11588,23 @@ void perf_event_free_task(struct task_struct *task)
			perf_free_event(event, ctx);

		mutex_unlock(&ctx->mutex);
		put_ctx(ctx);

		/*
		 * perf_event_release_kernel() could've stolen some of our
		 * child events and still have them on its free_list. In that
		 * case we must wait for these events to have been freed (in
		 * particular all their references to this task must've been
		 * dropped).
		 *
		 * Without this copy_process() will unconditionally free this
		 * task (irrespective of its reference count) and
		 * _free_event()'s put_task_struct(event->hw.target) will be a
		 * use-after-free.
		 *
		 * Wait for all events to drop their context reference.
		 */
		wait_var_event(&ctx->refcount, refcount_read(&ctx->refcount) == 1);
		put_ctx(ctx); /* must be last */
	}
}

+12 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: LGPL-2.1
#ifndef __TOOLS_LINUX_ZALLOC_H
#define __TOOLS_LINUX_ZALLOC_H

#include <stddef.h>

void *zalloc(size_t size);
void __zfree(void **ptr);

#define zfree(ptr) __zfree((void **)(ptr))

#endif // __TOOLS_LINUX_ZALLOC_H
Loading