Commit a1b3cf6d 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:
 "Misc fixes:

   - counter freezing related regression fix

   - uprobes race fix

   - Intel PMU unusual event combination fix

   - .. and diverse tooling fixes"

* 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  uprobes: Fix handle_swbp() vs. unregister() + register() race once more
  perf/x86/intel: Disallow precise_ip on BTS events
  perf/x86/intel: Add generic branch tracing check to intel_pmu_has_bts()
  perf/x86/intel: Move branch tracing setup to the Intel-specific source file
  perf/x86/intel: Fix regression by default disabling perfmon v4 interrupt handling
  perf tools beauty ioctl: Support new ISO7816 commands
  tools uapi asm-generic: Synchronize ioctls.h
  tools arch x86: Update tools's copy of cpufeatures.h
  tools headers uapi: Synchronize i915_drm.h
  perf tools: Restore proper cwd on return from mnt namespace
  tools build feature: Check if get_current_dir_name() is available
  perf tools: Fix crash on synthesizing the unit
parents 8d9f412d 09d3f015
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -856,7 +856,8 @@
			causing system reset or hang due to sending
			INIT from AP to BSP.

	disable_counter_freezing [HW]
	perf_v4_pmi=	[X86,INTEL]
			Format: <bool>
			Disable Intel PMU counter freezing feature.
			The feature only exists starting from
			Arch Perfmon v4 (Skylake and newer).
+0 −20
Original line number Diff line number Diff line
@@ -438,26 +438,6 @@ int x86_setup_perfctr(struct perf_event *event)
	if (config == -1LL)
		return -EINVAL;

	/*
	 * Branch tracing:
	 */
	if (attr->config == PERF_COUNT_HW_BRANCH_INSTRUCTIONS &&
	    !attr->freq && hwc->sample_period == 1) {
		/* BTS is not supported by this architecture. */
		if (!x86_pmu.bts_active)
			return -EOPNOTSUPP;

		/* BTS is currently only allowed for user-mode. */
		if (!attr->exclude_kernel)
			return -EOPNOTSUPP;

		/* disallow bts if conflicting events are present */
		if (x86_add_exclusive(x86_lbr_exclusive_lbr))
			return -EBUSY;

		event->destroy = hw_perf_lbr_event_destroy;
	}

	hwc->config |= config;

	return 0;
+52 −16
Original line number Diff line number Diff line
@@ -2306,14 +2306,18 @@ static int handle_pmi_common(struct pt_regs *regs, u64 status)
	return handled;
}

static bool disable_counter_freezing;
static bool disable_counter_freezing = true;
static int __init intel_perf_counter_freezing_setup(char *s)
{
	disable_counter_freezing = true;
	pr_info("Intel PMU Counter freezing feature disabled\n");
	bool res;

	if (kstrtobool(s, &res))
		return -EINVAL;

	disable_counter_freezing = !res;
	return 1;
}
__setup("disable_counter_freezing", intel_perf_counter_freezing_setup);
__setup("perf_v4_pmi=", intel_perf_counter_freezing_setup);

/*
 * Simplified handler for Arch Perfmon v4:
@@ -2470,16 +2474,7 @@ done:
static struct event_constraint *
intel_bts_constraints(struct perf_event *event)
{
	struct hw_perf_event *hwc = &event->hw;
	unsigned int hw_event, bts_event;

	if (event->attr.freq)
		return NULL;

	hw_event = hwc->config & INTEL_ARCH_EVENT_MASK;
	bts_event = x86_pmu.event_map(PERF_COUNT_HW_BRANCH_INSTRUCTIONS);

	if (unlikely(hw_event == bts_event && hwc->sample_period == 1))
	if (unlikely(intel_pmu_has_bts(event)))
		return &bts_constraint;

	return NULL;
@@ -3098,10 +3093,51 @@ static unsigned long intel_pmu_large_pebs_flags(struct perf_event *event)
	return flags;
}

static int intel_pmu_bts_config(struct perf_event *event)
{
	struct perf_event_attr *attr = &event->attr;

	if (unlikely(intel_pmu_has_bts(event))) {
		/* BTS is not supported by this architecture. */
		if (!x86_pmu.bts_active)
			return -EOPNOTSUPP;

		/* BTS is currently only allowed for user-mode. */
		if (!attr->exclude_kernel)
			return -EOPNOTSUPP;

		/* BTS is not allowed for precise events. */
		if (attr->precise_ip)
			return -EOPNOTSUPP;

		/* disallow bts if conflicting events are present */
		if (x86_add_exclusive(x86_lbr_exclusive_lbr))
			return -EBUSY;

		event->destroy = hw_perf_lbr_event_destroy;
	}

	return 0;
}

static int core_pmu_hw_config(struct perf_event *event)
{
	int ret = x86_pmu_hw_config(event);

	if (ret)
		return ret;

	return intel_pmu_bts_config(event);
}

static int intel_pmu_hw_config(struct perf_event *event)
{
	int ret = x86_pmu_hw_config(event);

	if (ret)
		return ret;

	ret = intel_pmu_bts_config(event);
	if (ret)
		return ret;

@@ -3127,7 +3163,7 @@ static int intel_pmu_hw_config(struct perf_event *event)
		/*
		 * BTS is set up earlier in this path, so don't account twice
		 */
		if (!intel_pmu_has_bts(event)) {
		if (!unlikely(intel_pmu_has_bts(event))) {
			/* disallow lbr if conflicting events are present */
			if (x86_add_exclusive(x86_lbr_exclusive_lbr))
				return -EBUSY;
@@ -3596,7 +3632,7 @@ static __initconst const struct x86_pmu core_pmu = {
	.enable_all		= core_pmu_enable_all,
	.enable			= core_pmu_enable_event,
	.disable		= x86_pmu_disable_event,
	.hw_config		= x86_pmu_hw_config,
	.hw_config		= core_pmu_hw_config,
	.schedule_events	= x86_schedule_events,
	.eventsel		= MSR_ARCH_PERFMON_EVENTSEL0,
	.perfctr		= MSR_ARCH_PERFMON_PERFCTR0,
+9 −4
Original line number Diff line number Diff line
@@ -859,11 +859,16 @@ static inline int amd_pmu_init(void)

static inline bool intel_pmu_has_bts(struct perf_event *event)
{
	if (event->attr.config == PERF_COUNT_HW_BRANCH_INSTRUCTIONS &&
	    !event->attr.freq && event->hw.sample_period == 1)
		return true;
	struct hw_perf_event *hwc = &event->hw;
	unsigned int hw_event, bts_event;

	if (event->attr.freq)
		return false;

	hw_event = hwc->config & INTEL_ARCH_EVENT_MASK;
	bts_event = x86_pmu.event_map(PERF_COUNT_HW_BRANCH_INSTRUCTIONS);

	return hw_event == bts_event && hwc->sample_period == 1;
}

int intel_pmu_save_and_restart(struct perf_event *event);
+10 −2
Original line number Diff line number Diff line
@@ -829,7 +829,7 @@ static int prepare_uprobe(struct uprobe *uprobe, struct file *file,
	BUG_ON((uprobe->offset & ~PAGE_MASK) +
			UPROBE_SWBP_INSN_SIZE > PAGE_SIZE);

	smp_wmb(); /* pairs with rmb() in find_active_uprobe() */
	smp_wmb(); /* pairs with the smp_rmb() in handle_swbp() */
	set_bit(UPROBE_COPY_INSN, &uprobe->flags);

 out:
@@ -2178,10 +2178,18 @@ static void handle_swbp(struct pt_regs *regs)
	 * After we hit the bp, _unregister + _register can install the
	 * new and not-yet-analyzed uprobe at the same address, restart.
	 */
	smp_rmb(); /* pairs with wmb() in install_breakpoint() */
	if (unlikely(!test_bit(UPROBE_COPY_INSN, &uprobe->flags)))
		goto out;

	/*
	 * Pairs with the smp_wmb() in prepare_uprobe().
	 *
	 * Guarantees that if we see the UPROBE_COPY_INSN bit set, then
	 * we must also see the stores to &uprobe->arch performed by the
	 * prepare_uprobe() call.
	 */
	smp_rmb();

	/* Tracing handlers use ->utask to communicate with fetch methods */
	if (!get_utask())
		goto out;
Loading