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

Commit a228b589 authored by Ingo Molnar's avatar Ingo Molnar
Browse files

Merge branch 'mce-inject' of git://git.kernel.org/pub/scm/linux/kernel/git/ras/ras into x86/mce

parents 715a4318 2c29d9dd
Loading
Loading
Loading
Loading
+5 −4
Original line number Diff line number Diff line
@@ -50,10 +50,11 @@
#define MCJ_CTX_MASK		3
#define MCJ_CTX(flags)		((flags) & MCJ_CTX_MASK)
#define MCJ_CTX_RANDOM		0    /* inject context: random */
#define MCJ_CTX_PROCESS		1    /* inject context: process */
#define MCJ_CTX_IRQ		2    /* inject context: IRQ */
#define MCJ_NMI_BROADCAST	4    /* do NMI broadcasting */
#define MCJ_EXCEPTION		8    /* raise as exception */
#define MCJ_CTX_PROCESS		0x1  /* inject context: process */
#define MCJ_CTX_IRQ		0x2  /* inject context: IRQ */
#define MCJ_NMI_BROADCAST	0x4  /* do NMI broadcasting */
#define MCJ_EXCEPTION		0x8  /* raise as exception */
#define MCJ_IRQ_BRAODCAST	0x10 /* do IRQ broadcasting */

/* Fields are zero when not available */
struct mce {
+30 −4
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/fs.h>
#include <linux/preempt.h>
#include <linux/smp.h>
#include <linux/notifier.h>
#include <linux/kdebug.h>
@@ -92,6 +93,18 @@ static int mce_raise_notify(unsigned int cmd, struct pt_regs *regs)
	return NMI_HANDLED;
}

static void mce_irq_ipi(void *info)
{
	int cpu = smp_processor_id();
	struct mce *m = &__get_cpu_var(injectm);

	if (cpumask_test_cpu(cpu, mce_inject_cpumask) &&
			m->inject_flags & MCJ_EXCEPTION) {
		cpumask_clear_cpu(cpu, mce_inject_cpumask);
		raise_exception(m, NULL);
	}
}

/* Inject mce on current CPU */
static int raise_local(void)
{
@@ -139,9 +152,10 @@ static void raise_mce(struct mce *m)
		return;

#ifdef CONFIG_X86_LOCAL_APIC
	if (m->inject_flags & MCJ_NMI_BROADCAST) {
	if (m->inject_flags & (MCJ_IRQ_BRAODCAST | MCJ_NMI_BROADCAST)) {
		unsigned long start;
		int cpu;

		get_online_cpus();
		cpumask_copy(mce_inject_cpumask, cpu_online_mask);
		cpumask_clear_cpu(get_cpu(), mce_inject_cpumask);
@@ -151,13 +165,25 @@ static void raise_mce(struct mce *m)
			    MCJ_CTX(mcpu->inject_flags) != MCJ_CTX_RANDOM)
				cpumask_clear_cpu(cpu, mce_inject_cpumask);
		}
		if (!cpumask_empty(mce_inject_cpumask))
			apic->send_IPI_mask(mce_inject_cpumask, NMI_VECTOR);
		if (!cpumask_empty(mce_inject_cpumask)) {
			if (m->inject_flags & MCJ_IRQ_BRAODCAST) {
				/*
				 * don't wait because mce_irq_ipi is necessary
				 * to be sync with following raise_local
				 */
				preempt_disable();
				smp_call_function_many(mce_inject_cpumask,
					mce_irq_ipi, NULL, 0);
				preempt_enable();
			} else if (m->inject_flags & MCJ_NMI_BROADCAST)
				apic->send_IPI_mask(mce_inject_cpumask,
						NMI_VECTOR);
		}
		start = jiffies;
		while (!cpumask_empty(mce_inject_cpumask)) {
			if (!time_before(jiffies, start + 2*HZ)) {
				printk(KERN_ERR
				"Timeout waiting for mce inject NMI %lx\n",
				"Timeout waiting for mce inject %lx\n",
					*cpumask_bits(mce_inject_cpumask));
				break;
			}