Commit c0e809e2 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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

Pull perf updates from Ingo Molnar:
 "Kernel side changes:

   - Ftrace is one of the last W^X violators (after this only KLP is
     left). These patches move it over to the generic text_poke()
     interface and thereby get rid of this oddity. This requires a
     surprising amount of surgery, by Peter Zijlstra.

   - x86/AMD PMUs: add support for 'Large Increment per Cycle Events' to
     count certain types of events that have a special, quirky hw ABI
     (by Kim Phillips)

   - kprobes fixes by Masami Hiramatsu

  Lots of tooling updates as well, the following subcommands were
  updated: annotate/report/top, c2c, clang, record, report/top TUI,
  sched timehist, tests; plus updates were done to the gtk ui, libperf,
  headers and the parser"

* 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (57 commits)
  perf/x86/amd: Add support for Large Increment per Cycle Events
  perf/x86/amd: Constrain Large Increment per Cycle events
  perf/x86/intel/rapl: Add Comet Lake support
  tracing: Initialize ret in syscall_enter_define_fields()
  perf header: Use last modification time for timestamp
  perf c2c: Fix return type for histogram sorting comparision functions
  perf beauty sockaddr: Fix augmented syscall format warning
  perf/ui/gtk: Fix gtk2 build
  perf ui gtk: Add missing zalloc object
  perf tools: Use %define api.pure full instead of %pure-parser
  libperf: Setup initial evlist::all_cpus value
  perf report: Fix no libunwind compiled warning break s390 issue
  perf tools: Support --prefix/--prefix-strip
  perf report: Clarify in help that --children is default
  tools build: Fix test-clang.cpp with Clang 8+
  perf clang: Fix build with Clang 9
  kprobes: Fix optimize_kprobe()/unoptimize_kprobe() cancellation logic
  tools lib: Fix builds when glibc contains strlcpy()
  perf report/top: Make 'e' visible in the help and make it toggle showing callchains
  perf report/top: Do not offer annotation for symbols without samples
  ...
parents 2180f214 0cc4bd8f
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -53,8 +53,8 @@ obj-$(CONFIG_HAVE_ARM_SCU) += smp_scu.o
obj-$(CONFIG_HAVE_ARM_TWD)	+= smp_twd.o
obj-$(CONFIG_ARM_ARCH_TIMER)	+= arch_timer.o
obj-$(CONFIG_FUNCTION_TRACER)	+= entry-ftrace.o
obj-$(CONFIG_DYNAMIC_FTRACE)	+= ftrace.o insn.o
obj-$(CONFIG_FUNCTION_GRAPH_TRACER)	+= ftrace.o insn.o
obj-$(CONFIG_DYNAMIC_FTRACE)	+= ftrace.o insn.o patch.o
obj-$(CONFIG_FUNCTION_GRAPH_TRACER)	+= ftrace.o insn.o patch.o
obj-$(CONFIG_JUMP_LABEL)	+= jump_label.o insn.o patch.o
obj-$(CONFIG_KEXEC)		+= machine_kexec.o relocate_kernel.o
# Main staffs in KPROBES are in arch/arm/probes/ .
+2 −8
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@
#include <asm/ftrace.h>
#include <asm/insn.h>
#include <asm/set_memory.h>
#include <asm/patch.h>

#ifdef CONFIG_THUMB2_KERNEL
#define	NOP		0xf85deb04	/* pop.w {lr} */
@@ -35,9 +36,7 @@ static int __ftrace_modify_code(void *data)
{
	int *command = data;

	set_kernel_text_rw();
	ftrace_modify_all_code(*command);
	set_kernel_text_ro();

	return 0;
}
@@ -59,13 +58,11 @@ static unsigned long adjust_address(struct dyn_ftrace *rec, unsigned long addr)

int ftrace_arch_code_modify_prepare(void)
{
	set_all_modules_text_rw();
	return 0;
}

int ftrace_arch_code_modify_post_process(void)
{
	set_all_modules_text_ro();
	/* Make sure any TLB misses during machine stop are cleared. */
	flush_tlb_all();
	return 0;
@@ -97,10 +94,7 @@ static int ftrace_modify_code(unsigned long pc, unsigned long old,
			return -EINVAL;
	}

	if (probe_kernel_write((void *)pc, &new, MCOUNT_INSN_SIZE))
		return -EPERM;

	flush_icache_range(pc, pc + MCOUNT_INSN_SIZE);
	__patch_text((void *)pc, new);

	return 0;
}
+0 −12
Original line number Diff line number Diff line
@@ -89,18 +89,6 @@ int __init ftrace_dyn_arch_init(void)
	return 0;
}

int ftrace_arch_code_modify_prepare(void)
{
	set_all_modules_text_rw();
	return 0;
}

int ftrace_arch_code_modify_post_process(void)
{
	set_all_modules_text_ro();
	return 0;
}

static unsigned long gen_sethi_insn(unsigned long addr)
{
	unsigned long opcode = 0x46000000;
+79 −30
Original line number Diff line number Diff line
@@ -14,6 +14,10 @@
static DEFINE_PER_CPU(unsigned long, perf_nmi_tstamp);
static unsigned long perf_nmi_window;

/* AMD Event 0xFFF: Merge.  Used with Large Increment per Cycle events */
#define AMD_MERGE_EVENT ((0xFULL << 32) | 0xFFULL)
#define AMD_MERGE_EVENT_ENABLE (AMD_MERGE_EVENT | ARCH_PERFMON_EVENTSEL_ENABLE)

static __initconst const u64 amd_hw_cache_event_ids
				[PERF_COUNT_HW_CACHE_MAX]
				[PERF_COUNT_HW_CACHE_OP_MAX]
@@ -301,6 +305,25 @@ static inline int amd_pmu_addr_offset(int index, bool eventsel)
	return offset;
}

/*
 * AMD64 events are detected based on their event codes.
 */
static inline unsigned int amd_get_event_code(struct hw_perf_event *hwc)
{
	return ((hwc->config >> 24) & 0x0f00) | (hwc->config & 0x00ff);
}

static inline bool amd_is_pair_event_code(struct hw_perf_event *hwc)
{
	if (!(x86_pmu.flags & PMU_FL_PAIR))
		return false;

	switch (amd_get_event_code(hwc)) {
	case 0x003:	return true;	/* Retired SSE/AVX FLOPs */
	default:	return false;
	}
}

static int amd_core_hw_config(struct perf_event *event)
{
	if (event->attr.exclude_host && event->attr.exclude_guest)
@@ -316,15 +339,10 @@ static int amd_core_hw_config(struct perf_event *event)
	else if (event->attr.exclude_guest)
		event->hw.config |= AMD64_EVENTSEL_HOSTONLY;

	return 0;
}
	if ((x86_pmu.flags & PMU_FL_PAIR) && amd_is_pair_event_code(&event->hw))
		event->hw.flags |= PERF_X86_EVENT_PAIR;

/*
 * AMD64 events are detected based on their event codes.
 */
static inline unsigned int amd_get_event_code(struct hw_perf_event *hwc)
{
	return ((hwc->config >> 24) & 0x0f00) | (hwc->config & 0x00ff);
	return 0;
}

static inline int amd_is_nb_event(struct hw_perf_event *hwc)
@@ -855,6 +873,29 @@ amd_get_event_constraints_f15h(struct cpu_hw_events *cpuc, int idx,
	}
}

static struct event_constraint pair_constraint;

static struct event_constraint *
amd_get_event_constraints_f17h(struct cpu_hw_events *cpuc, int idx,
			       struct perf_event *event)
{
	struct hw_perf_event *hwc = &event->hw;

	if (amd_is_pair_event_code(hwc))
		return &pair_constraint;

	return &unconstrained;
}

static void amd_put_event_constraints_f17h(struct cpu_hw_events *cpuc,
					   struct perf_event *event)
{
	struct hw_perf_event *hwc = &event->hw;

	if (is_counter_pair(hwc))
		--cpuc->n_pair;
}

static ssize_t amd_event_sysfs_show(char *page, u64 config)
{
	u64 event = (config & ARCH_PERFMON_EVENTSEL_EVENT) |
@@ -898,33 +939,15 @@ static __initconst const struct x86_pmu amd_pmu = {

static int __init amd_core_pmu_init(void)
{
	u64 even_ctr_mask = 0ULL;
	int i;

	if (!boot_cpu_has(X86_FEATURE_PERFCTR_CORE))
		return 0;

	/* Avoid calulating the value each time in the NMI handler */
	/* Avoid calculating the value each time in the NMI handler */
	perf_nmi_window = msecs_to_jiffies(100);

	switch (boot_cpu_data.x86) {
	case 0x15:
		pr_cont("Fam15h ");
		x86_pmu.get_event_constraints = amd_get_event_constraints_f15h;
		break;
	case 0x17:
		pr_cont("Fam17h ");
		/*
		 * In family 17h, there are no event constraints in the PMC hardware.
		 * We fallback to using default amd_get_event_constraints.
		 */
		break;
	case 0x18:
		pr_cont("Fam18h ");
		/* Using default amd_get_event_constraints. */
		break;
	default:
		pr_err("core perfctr but no constraints; unknown hardware!\n");
		return -ENODEV;
	}

	/*
	 * If core performance counter extensions exists, we must use
	 * MSR_F15H_PERF_CTL/MSR_F15H_PERF_CTR msrs. See also
@@ -939,6 +962,32 @@ static int __init amd_core_pmu_init(void)
	 */
	x86_pmu.amd_nb_constraints = 0;

	if (boot_cpu_data.x86 == 0x15) {
		pr_cont("Fam15h ");
		x86_pmu.get_event_constraints = amd_get_event_constraints_f15h;
	}
	if (boot_cpu_data.x86 >= 0x17) {
		pr_cont("Fam17h+ ");
		/*
		 * Family 17h and compatibles have constraints for Large
		 * Increment per Cycle events: they may only be assigned an
		 * even numbered counter that has a consecutive adjacent odd
		 * numbered counter following it.
		 */
		for (i = 0; i < x86_pmu.num_counters - 1; i += 2)
			even_ctr_mask |= 1 << i;

		pair_constraint = (struct event_constraint)
				    __EVENT_CONSTRAINT(0, even_ctr_mask, 0,
				    x86_pmu.num_counters / 2, 0,
				    PERF_X86_EVENT_PAIR);

		x86_pmu.get_event_constraints = amd_get_event_constraints_f17h;
		x86_pmu.put_event_constraints = amd_put_event_constraints_f17h;
		x86_pmu.perf_ctr_pair_en = AMD_MERGE_EVENT_ENABLE;
		x86_pmu.flags |= PMU_FL_PAIR;
	}

	pr_cont("core perfctr, ");
	return 0;
}
+59 −15
Original line number Diff line number Diff line
@@ -618,6 +618,7 @@ void x86_pmu_disable_all(void)
	int idx;

	for (idx = 0; idx < x86_pmu.num_counters; idx++) {
		struct hw_perf_event *hwc = &cpuc->events[idx]->hw;
		u64 val;

		if (!test_bit(idx, cpuc->active_mask))
@@ -627,6 +628,8 @@ void x86_pmu_disable_all(void)
			continue;
		val &= ~ARCH_PERFMON_EVENTSEL_ENABLE;
		wrmsrl(x86_pmu_config_addr(idx), val);
		if (is_counter_pair(hwc))
			wrmsrl(x86_pmu_config_addr(idx + 1), 0);
	}
}

@@ -699,7 +702,7 @@ struct sched_state {
	int	counter;	/* counter index */
	int	unassigned;	/* number of events to be assigned left */
	int	nr_gp;		/* number of GP counters used */
	unsigned long used[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
	u64	used;
};

/* Total max is X86_PMC_IDX_MAX, but we are O(n!) limited */
@@ -756,8 +759,12 @@ static bool perf_sched_restore_state(struct perf_sched *sched)
	sched->saved_states--;
	sched->state = sched->saved[sched->saved_states];

	/* continue with next counter: */
	clear_bit(sched->state.counter++, sched->state.used);
	/* this assignment didn't work out */
	/* XXX broken vs EVENT_PAIR */
	sched->state.used &= ~BIT_ULL(sched->state.counter);

	/* try the next one */
	sched->state.counter++;

	return true;
}
@@ -782,7 +789,12 @@ static bool __perf_sched_find_counter(struct perf_sched *sched)
	if (c->idxmsk64 & (~0ULL << INTEL_PMC_IDX_FIXED)) {
		idx = INTEL_PMC_IDX_FIXED;
		for_each_set_bit_from(idx, c->idxmsk, X86_PMC_IDX_MAX) {
			if (!__test_and_set_bit(idx, sched->state.used))
			u64 mask = BIT_ULL(idx);

			if (sched->state.used & mask)
				continue;

			sched->state.used |= mask;
			goto done;
		}
	}
@@ -790,13 +802,20 @@ static bool __perf_sched_find_counter(struct perf_sched *sched)
	/* Grab the first unused counter starting with idx */
	idx = sched->state.counter;
	for_each_set_bit_from(idx, c->idxmsk, INTEL_PMC_IDX_FIXED) {
		if (!__test_and_set_bit(idx, sched->state.used)) {
		u64 mask = BIT_ULL(idx);

		if (c->flags & PERF_X86_EVENT_PAIR)
			mask |= mask << 1;

		if (sched->state.used & mask)
			continue;

		if (sched->state.nr_gp++ >= sched->max_gp)
			return false;

		sched->state.used |= mask;
		goto done;
	}
	}

	return false;

@@ -872,12 +891,10 @@ EXPORT_SYMBOL_GPL(perf_assign_events);
int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign)
{
	struct event_constraint *c;
	unsigned long used_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
	struct perf_event *e;
	int n0, i, wmin, wmax, unsched = 0;
	struct hw_perf_event *hwc;

	bitmap_zero(used_mask, X86_PMC_IDX_MAX);
	u64 used_mask = 0;

	/*
	 * Compute the number of events already present; see x86_pmu_add(),
@@ -920,6 +937,8 @@ int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign)
	 * fastpath, try to reuse previous register
	 */
	for (i = 0; i < n; i++) {
		u64 mask;

		hwc = &cpuc->event_list[i]->hw;
		c = cpuc->event_constraint[i];

@@ -931,11 +950,16 @@ int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign)
		if (!test_bit(hwc->idx, c->idxmsk))
			break;

		mask = BIT_ULL(hwc->idx);
		if (is_counter_pair(hwc))
			mask |= mask << 1;

		/* not already used */
		if (test_bit(hwc->idx, used_mask))
		if (used_mask & mask)
			break;

		__set_bit(hwc->idx, used_mask);
		used_mask |= mask;

		if (assign)
			assign[i] = hwc->idx;
	}
@@ -958,6 +982,15 @@ int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign)
		    READ_ONCE(cpuc->excl_cntrs->exclusive_present))
			gpmax /= 2;

		/*
		 * Reduce the amount of available counters to allow fitting
		 * the extra Merge events needed by large increment events.
		 */
		if (x86_pmu.flags & PMU_FL_PAIR) {
			gpmax = x86_pmu.num_counters - cpuc->n_pair;
			WARN_ON(gpmax <= 0);
		}

		unsched = perf_assign_events(cpuc->event_constraint, n, wmin,
					     wmax, gpmax, assign);
	}
@@ -1038,6 +1071,8 @@ static int collect_events(struct cpu_hw_events *cpuc, struct perf_event *leader,
			return -EINVAL;
		cpuc->event_list[n] = leader;
		n++;
		if (is_counter_pair(&leader->hw))
			cpuc->n_pair++;
	}
	if (!dogrp)
		return n;
@@ -1052,6 +1087,8 @@ static int collect_events(struct cpu_hw_events *cpuc, struct perf_event *leader,

		cpuc->event_list[n] = event;
		n++;
		if (is_counter_pair(&event->hw))
			cpuc->n_pair++;
	}
	return n;
}
@@ -1237,6 +1274,13 @@ int x86_perf_event_set_period(struct perf_event *event)

	wrmsrl(hwc->event_base, (u64)(-left) & x86_pmu.cntval_mask);

	/*
	 * Clear the Merge event counter's upper 16 bits since
	 * we currently declare a 48-bit counter width
	 */
	if (is_counter_pair(hwc))
		wrmsrl(x86_pmu_event_addr(idx + 1), 0);

	/*
	 * Due to erratum on certan cpu we need
	 * a second write to be sure the register
Loading