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

Commit 51756a50 authored by Borislav Petkov's avatar Borislav Petkov
Browse files

EDAC, mce_amd_inj: Add an injector function



Selectively inject either a real MCE or a sw-only version which
exercises the decoding path only. The hardware-injected MCE triggers a
machine check exception (#MC) so that the MCE handler can be bothered to
do something too.

Signed-off-by: default avatarBorislav Petkov <bp@suse.de>
parent b18f3864
Loading
Loading
Loading
Loading
+51 −2
Original line number Original line Diff line number Diff line
@@ -14,6 +14,7 @@
#include <linux/debugfs.h>
#include <linux/debugfs.h>
#include <linux/device.h>
#include <linux/device.h>
#include <linux/module.h>
#include <linux/module.h>
#include <linux/cpu.h>
#include <asm/mce.h>
#include <asm/mce.h>


#include "mce_amd.h"
#include "mce_amd.h"
@@ -116,6 +117,55 @@ static int inj_extcpu_set(void *data, u64 val)


DEFINE_SIMPLE_ATTRIBUTE(extcpu_fops, inj_extcpu_get, inj_extcpu_set, "%llu\n");
DEFINE_SIMPLE_ATTRIBUTE(extcpu_fops, inj_extcpu_get, inj_extcpu_set, "%llu\n");


static void trigger_mce(void *info)
{
	asm volatile("int $18");
}

static void do_inject(void)
{
	u64 mcg_status = 0;
	unsigned int cpu = i_mce.extcpu;
	u8 b = i_mce.bank;

	if (!(i_mce.inject_flags & MCJ_EXCEPTION)) {
		amd_decode_mce(NULL, 0, &i_mce);
		return;
	}

	get_online_cpus();
	if (!cpu_online(cpu))
		goto err;

	/* prep MCE global settings for the injection */
	mcg_status = MCG_STATUS_MCIP | MCG_STATUS_EIPV;

	if (!(i_mce.status & MCI_STATUS_PCC))
		mcg_status |= MCG_STATUS_RIPV;

	toggle_hw_mce_inject(cpu, true);

	wrmsr_on_cpu(cpu, MSR_IA32_MCG_STATUS,
		     (u32)mcg_status, (u32)(mcg_status >> 32));

	wrmsr_on_cpu(cpu, MSR_IA32_MCx_STATUS(b),
		     (u32)i_mce.status, (u32)(i_mce.status >> 32));

	wrmsr_on_cpu(cpu, MSR_IA32_MCx_ADDR(b),
		     (u32)i_mce.addr, (u32)(i_mce.addr >> 32));

	wrmsr_on_cpu(cpu, MSR_IA32_MCx_MISC(b),
		     (u32)i_mce.misc, (u32)(i_mce.misc >> 32));

	toggle_hw_mce_inject(cpu, false);

	smp_call_function_single(cpu, trigger_mce, NULL, 0);

err:
	put_online_cpus();

}

/*
/*
 * This denotes into which bank we're injecting and triggers
 * This denotes into which bank we're injecting and triggers
 * the injection, at the same time.
 * the injection, at the same time.
@@ -132,8 +182,7 @@ static int inj_bank_set(void *data, u64 val)
	}
	}


	m->bank = val;
	m->bank = val;

	do_inject();
	amd_decode_mce(NULL, 0, m);


	return 0;
	return 0;
}
}