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

Commit 16ec54ad 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:

 - an s2ram related fix on AMD systems

 - a perf fault handling bug that is relatively old but which has become
   much easier to trigger in v3.13 after commit e00b12e6 ("perf/x86:
   Further optimize copy_from_user_nmi()")

* 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  perf/x86/amd/ibs: Fix waking up from S3 for AMD family 10h
  x86, mm, perf: Allow recursive faults from interrupts
parents 7d0d46da bee09ed9
Loading
Loading
Loading
Loading
+45 −8
Original line number Diff line number Diff line
@@ -10,6 +10,7 @@
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/ptrace.h>
#include <linux/syscore_ops.h>

#include <asm/apic.h>

@@ -816,6 +817,18 @@ static int force_ibs_eilvt_setup(void)
	return ret;
}

static void ibs_eilvt_setup(void)
{
	/*
	 * Force LVT offset assignment for family 10h: The offsets are
	 * not assigned by the BIOS for this family, so the OS is
	 * responsible for doing it. If the OS assignment fails, fall
	 * back to BIOS settings and try to setup this.
	 */
	if (boot_cpu_data.x86 == 0x10)
		force_ibs_eilvt_setup();
}

static inline int get_ibs_lvt_offset(void)
{
	u64 val;
@@ -851,6 +864,36 @@ static void clear_APIC_ibs(void *dummy)
		setup_APIC_eilvt(offset, 0, APIC_EILVT_MSG_FIX, 1);
}

#ifdef CONFIG_PM

static int perf_ibs_suspend(void)
{
	clear_APIC_ibs(NULL);
	return 0;
}

static void perf_ibs_resume(void)
{
	ibs_eilvt_setup();
	setup_APIC_ibs(NULL);
}

static struct syscore_ops perf_ibs_syscore_ops = {
	.resume		= perf_ibs_resume,
	.suspend	= perf_ibs_suspend,
};

static void perf_ibs_pm_init(void)
{
	register_syscore_ops(&perf_ibs_syscore_ops);
}

#else

static inline void perf_ibs_pm_init(void) { }

#endif

static int
perf_ibs_cpu_notifier(struct notifier_block *self, unsigned long action, void *hcpu)
{
@@ -877,18 +920,12 @@ static __init int amd_ibs_init(void)
	if (!caps)
		return -ENODEV;	/* ibs not supported by the cpu */

	/*
	 * Force LVT offset assignment for family 10h: The offsets are
	 * not assigned by the BIOS for this family, so the OS is
	 * responsible for doing it. If the OS assignment fails, fall
	 * back to BIOS settings and try to setup this.
	 */
	if (boot_cpu_data.x86 == 0x10)
		force_ibs_eilvt_setup();
	ibs_eilvt_setup();

	if (!ibs_eilvt_valid())
		goto out;

	perf_ibs_pm_init();
	get_online_cpus();
	ibs_caps = caps;
	/* make ibs_caps visible to other cpus: */
+18 −0
Original line number Diff line number Diff line
@@ -641,6 +641,20 @@ no_context(struct pt_regs *regs, unsigned long error_code,

	/* Are we prepared to handle this kernel fault? */
	if (fixup_exception(regs)) {
		/*
		 * Any interrupt that takes a fault gets the fixup. This makes
		 * the below recursive fault logic only apply to a faults from
		 * task context.
		 */
		if (in_interrupt())
			return;

		/*
		 * Per the above we're !in_interrupt(), aka. task context.
		 *
		 * In this case we need to make sure we're not recursively
		 * faulting through the emulate_vsyscall() logic.
		 */
		if (current_thread_info()->sig_on_uaccess_error && signal) {
			tsk->thread.trap_nr = X86_TRAP_PF;
			tsk->thread.error_code = error_code | PF_USER;
@@ -649,6 +663,10 @@ no_context(struct pt_regs *regs, unsigned long error_code,
			/* XXX: hwpoison faults will set the wrong code. */
			force_sig_info_fault(signal, si_code, address, tsk, 0);
		}

		/*
		 * Barring that, we can do the fixup and be happy.
		 */
		return;
	}