Skip to content

Commit

Permalink
Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/…
Browse files Browse the repository at this point in the history
…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
  ...
  • Loading branch information
torvalds committed Jul 14, 2019
2 parents 0c85ce1 + e4557c1 commit 1d03985
Show file tree
Hide file tree
Showing 151 changed files with 457 additions and 308 deletions.
15 changes: 11 additions & 4 deletions arch/x86/events/amd/uncore.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
8 changes: 3 additions & 5 deletions arch/x86/events/intel/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -2161,12 +2161,10 @@ 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;
}

x86_pmu_disable_event(event);
else
x86_pmu_disable_event(event);

/*
* Needs to be called after x86_pmu_disable_event,
Expand Down
5 changes: 5 additions & 0 deletions include/linux/perf_event.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
83 changes: 63 additions & 20 deletions kernel/events/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand All @@ -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;

Expand Down Expand Up @@ -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;

/*
Expand Down Expand Up @@ -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() */
Expand All @@ -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) {
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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):
*/
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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 */
}
}

Expand Down
12 changes: 12 additions & 0 deletions tools/include/linux/zalloc.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// 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
15 changes: 15 additions & 0 deletions tools/lib/zalloc.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// SPDX-License-Identifier: LGPL-2.1

#include <stdlib.h>
#include <linux/zalloc.h>

void *zalloc(size_t size)
{
return calloc(1, size);
}

void __zfree(void **ptr)
{
free(*ptr);
*ptr = NULL;
}
1 change: 1 addition & 0 deletions tools/perf/MANIFEST
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ tools/lib/find_bit.c
tools/lib/bitmap.c
tools/lib/str_error_r.c
tools/lib/vsprintf.c
tools/lib/zalloc.c
1 change: 1 addition & 0 deletions tools/perf/arch/arm/annotate/instructions.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/compiler.h>
#include <linux/zalloc.h>
#include <sys/types.h>
#include <regex.h>

Expand Down
1 change: 1 addition & 0 deletions tools/perf/arch/arm/util/auxtrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include <stdbool.h>
#include <linux/coresight-pmu.h>
#include <linux/zalloc.h>

#include "../../util/auxtrace.h"
#include "../../util/evlist.h"
Expand Down
1 change: 1 addition & 0 deletions tools/perf/arch/arm/util/cs-etm.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <linux/kernel.h>
#include <linux/log2.h>
#include <linux/types.h>
#include <linux/zalloc.h>

#include "cs-etm.h"
#include "../../perf.h"
Expand Down
1 change: 1 addition & 0 deletions tools/perf/arch/arm64/util/arm-spe.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <linux/types.h>
#include <linux/bitops.h>
#include <linux/log2.h>
#include <linux/zalloc.h>
#include <time.h>

#include "../../util/cpumap.h"
Expand Down
3 changes: 2 additions & 1 deletion tools/perf/arch/common.c
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
// SPDX-License-Identifier: GPL-2.0
#include <stdio.h>
#include <stdlib.h>
#include "common.h"
#include "../util/env.h"
#include "../util/util.h"
#include "../util/debug.h"
#include <linux/zalloc.h>

const char *const arc_triplets[] = {
"arc-linux-",
Expand Down
4 changes: 3 additions & 1 deletion tools/perf/arch/powerpc/util/perf_regs.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@
#include <errno.h>
#include <string.h>
#include <regex.h>
#include <linux/zalloc.h>

#include "../../perf.h"
#include "../../util/util.h"
#include "../../util/perf_regs.h"
#include "../../util/debug.h"

#include <linux/kernel.h>

const struct sample_reg sample_reg_masks[] = {
SMPL_REG(r0, PERF_REG_POWERPC_R0),
SMPL_REG(r1, PERF_REG_POWERPC_R1),
Expand Down
1 change: 1 addition & 0 deletions tools/perf/arch/s390/util/auxtrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <linux/types.h>
#include <linux/bitops.h>
#include <linux/log2.h>
#include <linux/zalloc.h>

#include "../../util/evlist.h"
#include "../../util/auxtrace.h"
Expand Down
3 changes: 2 additions & 1 deletion tools/perf/arch/s390/util/header.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@
#include <stdio.h>
#include <string.h>
#include <linux/ctype.h>
#include <linux/kernel.h>
#include <linux/zalloc.h>

#include "../../util/header.h"
#include "../../util/util.h"

#define SYSINFO_MANU "Manufacturer:"
#define SYSINFO_TYPE "Type:"
Expand Down
2 changes: 1 addition & 1 deletion tools/perf/arch/x86/util/event.c
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/types.h>
#include <linux/string.h>
#include <linux/zalloc.h>

#include "../../util/machine.h"
#include "../../util/tool.h"
#include "../../util/map.h"
#include "../../util/util.h"
#include "../../util/debug.h"

#if defined(__x86_64__)
Expand Down
2 changes: 1 addition & 1 deletion tools/perf/arch/x86/util/intel-bts.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@
#include <linux/types.h>
#include <linux/bitops.h>
#include <linux/log2.h>
#include <linux/zalloc.h>

#include "../../util/cpumap.h"
#include "../../util/evsel.h"
#include "../../util/evlist.h"
#include "../../util/session.h"
#include "../../util/util.h"
#include "../../util/pmu.h"
#include "../../util/debug.h"
#include "../../util/tsc.h"
Expand Down
2 changes: 1 addition & 1 deletion tools/perf/arch/x86/util/intel-pt.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <linux/types.h>
#include <linux/bitops.h>
#include <linux/log2.h>
#include <linux/zalloc.h>
#include <cpuid.h>

#include "../../perf.h"
Expand All @@ -25,7 +26,6 @@
#include "../../util/auxtrace.h"
#include "../../util/tsc.h"
#include "../../util/intel-pt.h"
#include "../../util/util.h"

#define KiB(x) ((x) * 1024)
#define MiB(x) ((x) * 1024 * 1024)
Expand Down
Loading

0 comments on commit 1d03985

Please sign in to comment.