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

Commit 0b20e59c authored by Ingo Molnar's avatar Ingo Molnar
Browse files

Merge branch 'perf/urgent' into perf/core, to resolve conflict



 Conflicts:
	arch/x86/events/intel/pt.c

Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parents a8944c5b cf3beb7c
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -115,7 +115,7 @@ static __initconst const u64 amd_hw_cache_event_ids
/*
 * AMD Performance Monitor K7 and later.
 */
static const u64 amd_perfmon_event_map[] =
static const u64 amd_perfmon_event_map[PERF_COUNT_HW_MAX] =
{
  [PERF_COUNT_HW_CPU_CYCLES]			= 0x0076,
  [PERF_COUNT_HW_INSTRUCTIONS]			= 0x00c0,
+4 −2
Original line number Diff line number Diff line
@@ -64,7 +64,7 @@ static enum {

#define LBR_PLM (LBR_KERNEL | LBR_USER)

#define LBR_SEL_MASK	0x1ff	/* valid bits in LBR_SELECT */
#define LBR_SEL_MASK	0x3ff	/* valid bits in LBR_SELECT */
#define LBR_NOT_SUPP	-1	/* LBR filter not supported */
#define LBR_IGN		0	/* ignored */

@@ -621,8 +621,10 @@ static int intel_pmu_setup_hw_lbr_filter(struct perf_event *event)
	 * The first 9 bits (LBR_SEL_MASK) in LBR_SELECT operate
	 * in suppress mode. So LBR_SELECT should be set to
	 * (~mask & LBR_SEL_MASK) | (mask & ~LBR_SEL_MASK)
	 * But the 10th bit LBR_CALL_STACK does not operate
	 * in suppress mode.
	 */
	reg->config = mask ^ x86_pmu.lbr_sel_mask;
	reg->config = mask ^ (x86_pmu.lbr_sel_mask & ~LBR_CALL_STACK);

	if ((br_type & PERF_SAMPLE_BRANCH_NO_CYCLES) &&
	    (br_type & PERF_SAMPLE_BRANCH_NO_FLAGS) &&
+64 −11
Original line number Diff line number Diff line
@@ -136,9 +136,21 @@ static int __init pt_pmu_hw_init(void)
	struct dev_ext_attribute *de_attrs;
	struct attribute **attrs;
	size_t size;
	u64 reg;
	int ret;
	long i;

	if (boot_cpu_has(X86_FEATURE_VMX)) {
		/*
		 * Intel SDM, 36.5 "Tracing post-VMXON" says that
		 * "IA32_VMX_MISC[bit 14]" being 1 means PT can trace
		 * post-VMXON.
		 */
		rdmsrl(MSR_IA32_VMX_MISC, reg);
		if (reg & BIT(14))
			pt_pmu.vmx = true;
	}

	attrs = NULL;

	for (i = 0; i < PT_CPUID_LEAVES; i++) {
@@ -269,20 +281,23 @@ static void pt_config(struct perf_event *event)

	reg |= (event->attr.config & PT_CONFIG_MASK);

	event->hw.config = reg;
	wrmsrl(MSR_IA32_RTIT_CTL, reg);
}

static void pt_config_start(bool start)
static void pt_config_stop(struct perf_event *event)
{
	u64 ctl;
	u64 ctl = READ_ONCE(event->hw.config);

	/* may be already stopped by a PMI */
	if (!(ctl & RTIT_CTL_TRACEEN))
		return;

	rdmsrl(MSR_IA32_RTIT_CTL, ctl);
	if (start)
		ctl |= RTIT_CTL_TRACEEN;
	else
	ctl &= ~RTIT_CTL_TRACEEN;
	wrmsrl(MSR_IA32_RTIT_CTL, ctl);

	WRITE_ONCE(event->hw.config, ctl);

	/*
	 * A wrmsr that disables trace generation serializes other PT
	 * registers and causes all data packets to be written to memory,
@@ -291,7 +306,6 @@ static void pt_config_start(bool start)
	 * The below WMB, separating data store and aux_head store matches
	 * the consumer's RMB that separates aux_head load and data load.
	 */
	if (!start)
	wmb();
}

@@ -922,11 +936,17 @@ void intel_pt_interrupt(void)
	if (!ACCESS_ONCE(pt->handle_nmi))
		return;

	pt_config_start(false);
	/*
	 * If VMX is on and PT does not support it, don't touch anything.
	 */
	if (READ_ONCE(pt->vmx_on))
		return;

	if (!event)
		return;

	pt_config_stop(event);

	buf = perf_get_aux(&pt->handle);
	if (!buf)
		return;
@@ -963,6 +983,35 @@ void intel_pt_interrupt(void)
	}
}

void intel_pt_handle_vmx(int on)
{
	struct pt *pt = this_cpu_ptr(&pt_ctx);
	struct perf_event *event;
	unsigned long flags;

	/* PT plays nice with VMX, do nothing */
	if (pt_pmu.vmx)
		return;

	/*
	 * VMXON will clear RTIT_CTL.TraceEn; we need to make
	 * sure to not try to set it while VMX is on. Disable
	 * interrupts to avoid racing with pmu callbacks;
	 * concurrent PMI should be handled fine.
	 */
	local_irq_save(flags);
	WRITE_ONCE(pt->vmx_on, on);

	if (on) {
		/* prevent pt_config_stop() from writing RTIT_CTL */
		event = pt->handle.event;
		if (event)
			event->hw.config = 0;
	}
	local_irq_restore(flags);
}
EXPORT_SYMBOL_GPL(intel_pt_handle_vmx);

/*
 * PMU callbacks
 */
@@ -973,6 +1022,9 @@ static void pt_event_start(struct perf_event *event, int mode)
	struct pt *pt = this_cpu_ptr(&pt_ctx);
	struct pt_buffer *buf;

	if (READ_ONCE(pt->vmx_on))
		return;

	buf = perf_aux_output_begin(&pt->handle, event);
	if (!buf)
		goto fail_stop;
@@ -1007,7 +1059,8 @@ static void pt_event_stop(struct perf_event *event, int mode)
	 * see comment in intel_pt_interrupt().
	 */
	ACCESS_ONCE(pt->handle_nmi) = 0;
	pt_config_start(false);

	pt_config_stop(event);

	if (event->hw.state == PERF_HES_STOPPED)
		return;
+3 −0
Original line number Diff line number Diff line
@@ -65,6 +65,7 @@ enum pt_capabilities {
struct pt_pmu {
	struct pmu		pmu;
	u32			caps[PT_CPUID_REGS_NUM * PT_CPUID_LEAVES];
	bool			vmx;
};

/**
@@ -107,10 +108,12 @@ struct pt_buffer {
 * struct pt - per-cpu pt context
 * @handle:	perf output handle
 * @handle_nmi:	do handle PT PMI on this cpu, there's an active event
 * @vmx_on:	1 if VMX is ON on this cpu
 */
struct pt {
	struct perf_output_handle handle;
	int			handle_nmi;
	int			vmx_on;
};

#endif /* __INTEL_PT_H__ */
+4 −0
Original line number Diff line number Diff line
@@ -285,6 +285,10 @@ static inline void perf_events_lapic_init(void) { }
static inline void perf_check_microcode(void) { }
#endif

#ifdef CONFIG_CPU_SUP_INTEL
 extern void intel_pt_handle_vmx(int on);
#endif

#if defined(CONFIG_PERF_EVENTS) && defined(CONFIG_CPU_SUP_AMD)
 extern void amd_pmu_enable_virt(void);
 extern void amd_pmu_disable_virt(void);
Loading