1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Machine check injection support.
4 * Copyright 2008 Intel Corporation.
5 *
6 * Authors:
7 * Andi Kleen
8 * Ying Huang
9 *
10 * The AMD part (from mce_amd_inj.c): a simple MCE injection facility
11 * for testing different aspects of the RAS code. This driver should be
12 * built as module so that it can be loaded on production kernels for
13 * testing purposes.
14 *
15 * Copyright (c) 2010-17:  Borislav Petkov <bp@alien8.de>
16 *			   Advanced Micro Devices Inc.
17 */
18
19#include <linux/cpu.h>
20#include <linux/debugfs.h>
21#include <linux/kernel.h>
22#include <linux/module.h>
23#include <linux/notifier.h>
24#include <linux/pci.h>
25#include <linux/uaccess.h>
26
27#include <asm/amd_nb.h>
28#include <asm/apic.h>
29#include <asm/irq_vectors.h>
30#include <asm/mce.h>
31#include <asm/nmi.h>
32#include <asm/smp.h>
33
34#include "internal.h"
35
36static bool hw_injection_possible = true;
37
38/*
39 * Collect all the MCi_XXX settings
40 */
41static struct mce i_mce;
42static struct dentry *dfs_inj;
43
44#define MAX_FLAG_OPT_SIZE	4
45#define NBCFG			0x44
46
47enum injection_type {
48	SW_INJ = 0,	/* SW injection, simply decode the error */
49	HW_INJ,		/* Trigger a #MC */
50	DFR_INT_INJ,    /* Trigger Deferred error interrupt */
51	THR_INT_INJ,    /* Trigger threshold interrupt */
52	N_INJ_TYPES,
53};
54
55static const char * const flags_options[] = {
56	[SW_INJ] = "sw",
57	[HW_INJ] = "hw",
58	[DFR_INT_INJ] = "df",
59	[THR_INT_INJ] = "th",
60	NULL
61};
62
63/* Set default injection to SW_INJ */
64static enum injection_type inj_type = SW_INJ;
65
66#define MCE_INJECT_SET(reg)						\
67static int inj_##reg##_set(void *data, u64 val)				\
68{									\
69	struct mce *m = (struct mce *)data;				\
70									\
71	m->reg = val;							\
72	return 0;							\
73}
74
75MCE_INJECT_SET(status);
76MCE_INJECT_SET(misc);
77MCE_INJECT_SET(addr);
78MCE_INJECT_SET(synd);
79
80#define MCE_INJECT_GET(reg)						\
81static int inj_##reg##_get(void *data, u64 *val)			\
82{									\
83	struct mce *m = (struct mce *)data;				\
84									\
85	*val = m->reg;							\
86	return 0;							\
87}
88
89MCE_INJECT_GET(status);
90MCE_INJECT_GET(misc);
91MCE_INJECT_GET(addr);
92MCE_INJECT_GET(synd);
93MCE_INJECT_GET(ipid);
94
95DEFINE_SIMPLE_ATTRIBUTE(status_fops, inj_status_get, inj_status_set, "%llx\n");
96DEFINE_SIMPLE_ATTRIBUTE(misc_fops, inj_misc_get, inj_misc_set, "%llx\n");
97DEFINE_SIMPLE_ATTRIBUTE(addr_fops, inj_addr_get, inj_addr_set, "%llx\n");
98DEFINE_SIMPLE_ATTRIBUTE(synd_fops, inj_synd_get, inj_synd_set, "%llx\n");
99
100/* Use the user provided IPID value on a sw injection. */
101static int inj_ipid_set(void *data, u64 val)
102{
103	struct mce *m = (struct mce *)data;
104
105	if (cpu_feature_enabled(X86_FEATURE_SMCA)) {
106		if (inj_type == SW_INJ)
107			m->ipid = val;
108	}
109
110	return 0;
111}
112
113DEFINE_SIMPLE_ATTRIBUTE(ipid_fops, inj_ipid_get, inj_ipid_set, "%llx\n");
114
115static void setup_inj_struct(struct mce *m)
116{
117	memset(m, 0, sizeof(struct mce));
118
119	m->cpuvendor = boot_cpu_data.x86_vendor;
120	m->time	     = ktime_get_real_seconds();
121	m->cpuid     = cpuid_eax(1);
122	m->microcode = boot_cpu_data.microcode;
123}
124
125/* Update fake mce registers on current CPU. */
126static void inject_mce(struct mce *m)
127{
128	struct mce *i = &per_cpu(injectm, m->extcpu);
129
130	/* Make sure no one reads partially written injectm */
131	i->finished = 0;
132	mb();
133	m->finished = 0;
134	/* First set the fields after finished */
135	i->extcpu = m->extcpu;
136	mb();
137	/* Now write record in order, finished last (except above) */
138	memcpy(i, m, sizeof(struct mce));
139	/* Finally activate it */
140	mb();
141	i->finished = 1;
142}
143
144static void raise_poll(struct mce *m)
145{
146	unsigned long flags;
147	mce_banks_t b;
148
149	memset(&b, 0xff, sizeof(mce_banks_t));
150	local_irq_save(flags);
151	machine_check_poll(0, &b);
152	local_irq_restore(flags);
153	m->finished = 0;
154}
155
156static void raise_exception(struct mce *m, struct pt_regs *pregs)
157{
158	struct pt_regs regs;
159	unsigned long flags;
160
161	if (!pregs) {
162		memset(&regs, 0, sizeof(struct pt_regs));
163		regs.ip = m->ip;
164		regs.cs = m->cs;
165		pregs = &regs;
166	}
167	/* do_machine_check() expects interrupts disabled -- at least */
168	local_irq_save(flags);
169	do_machine_check(pregs);
170	local_irq_restore(flags);
171	m->finished = 0;
172}
173
174static cpumask_var_t mce_inject_cpumask;
175static DEFINE_MUTEX(mce_inject_mutex);
176
177static int mce_raise_notify(unsigned int cmd, struct pt_regs *regs)
178{
179	int cpu = smp_processor_id();
180	struct mce *m = this_cpu_ptr(&injectm);
181	if (!cpumask_test_cpu(cpu, mce_inject_cpumask))
182		return NMI_DONE;
183	cpumask_clear_cpu(cpu, mce_inject_cpumask);
184	if (m->inject_flags & MCJ_EXCEPTION)
185		raise_exception(m, regs);
186	else if (m->status)
187		raise_poll(m);
188	return NMI_HANDLED;
189}
190
191static void mce_irq_ipi(void *info)
192{
193	int cpu = smp_processor_id();
194	struct mce *m = this_cpu_ptr(&injectm);
195
196	if (cpumask_test_cpu(cpu, mce_inject_cpumask) &&
197			m->inject_flags & MCJ_EXCEPTION) {
198		cpumask_clear_cpu(cpu, mce_inject_cpumask);
199		raise_exception(m, NULL);
200	}
201}
202
203/* Inject mce on current CPU */
204static int raise_local(void)
205{
206	struct mce *m = this_cpu_ptr(&injectm);
207	int context = MCJ_CTX(m->inject_flags);
208	int ret = 0;
209	int cpu = m->extcpu;
210
211	if (m->inject_flags & MCJ_EXCEPTION) {
212		pr_info("Triggering MCE exception on CPU %d\n", cpu);
213		switch (context) {
214		case MCJ_CTX_IRQ:
215			/*
216			 * Could do more to fake interrupts like
217			 * calling irq_enter, but the necessary
218			 * machinery isn't exported currently.
219			 */
220			fallthrough;
221		case MCJ_CTX_PROCESS:
222			raise_exception(m, NULL);
223			break;
224		default:
225			pr_info("Invalid MCE context\n");
226			ret = -EINVAL;
227		}
228		pr_info("MCE exception done on CPU %d\n", cpu);
229	} else if (m->status) {
230		pr_info("Starting machine check poll CPU %d\n", cpu);
231		raise_poll(m);
232		mce_notify_irq();
233		pr_info("Machine check poll done on CPU %d\n", cpu);
234	} else
235		m->finished = 0;
236
237	return ret;
238}
239
240static void __maybe_unused raise_mce(struct mce *m)
241{
242	int context = MCJ_CTX(m->inject_flags);
243
244	inject_mce(m);
245
246	if (context == MCJ_CTX_RANDOM)
247		return;
248
249	if (m->inject_flags & (MCJ_IRQ_BROADCAST | MCJ_NMI_BROADCAST)) {
250		unsigned long start;
251		int cpu;
252
253		cpus_read_lock();
254		cpumask_copy(mce_inject_cpumask, cpu_online_mask);
255		cpumask_clear_cpu(get_cpu(), mce_inject_cpumask);
256		for_each_online_cpu(cpu) {
257			struct mce *mcpu = &per_cpu(injectm, cpu);
258			if (!mcpu->finished ||
259			    MCJ_CTX(mcpu->inject_flags) != MCJ_CTX_RANDOM)
260				cpumask_clear_cpu(cpu, mce_inject_cpumask);
261		}
262		if (!cpumask_empty(mce_inject_cpumask)) {
263			if (m->inject_flags & MCJ_IRQ_BROADCAST) {
264				/*
265				 * don't wait because mce_irq_ipi is necessary
266				 * to be sync with following raise_local
267				 */
268				preempt_disable();
269				smp_call_function_many(mce_inject_cpumask,
270					mce_irq_ipi, NULL, 0);
271				preempt_enable();
272			} else if (m->inject_flags & MCJ_NMI_BROADCAST)
273				__apic_send_IPI_mask(mce_inject_cpumask, NMI_VECTOR);
274		}
275		start = jiffies;
276		while (!cpumask_empty(mce_inject_cpumask)) {
277			if (!time_before(jiffies, start + 2*HZ)) {
278				pr_err("Timeout waiting for mce inject %lx\n",
279					*cpumask_bits(mce_inject_cpumask));
280				break;
281			}
282			cpu_relax();
283		}
284		raise_local();
285		put_cpu();
286		cpus_read_unlock();
287	} else {
288		preempt_disable();
289		raise_local();
290		preempt_enable();
291	}
292}
293
294static int mce_inject_raise(struct notifier_block *nb, unsigned long val,
295			    void *data)
296{
297	struct mce *m = (struct mce *)data;
298
299	if (!m)
300		return NOTIFY_DONE;
301
302	mutex_lock(&mce_inject_mutex);
303	raise_mce(m);
304	mutex_unlock(&mce_inject_mutex);
305
306	return NOTIFY_DONE;
307}
308
309static struct notifier_block inject_nb = {
310	.notifier_call  = mce_inject_raise,
311};
312
313/*
314 * Caller needs to be make sure this cpu doesn't disappear
315 * from under us, i.e.: get_cpu/put_cpu.
316 */
317static int toggle_hw_mce_inject(unsigned int cpu, bool enable)
318{
319	u32 l, h;
320	int err;
321
322	err = rdmsr_on_cpu(cpu, MSR_K7_HWCR, &l, &h);
323	if (err) {
324		pr_err("%s: error reading HWCR\n", __func__);
325		return err;
326	}
327
328	enable ? (l |= BIT(18)) : (l &= ~BIT(18));
329
330	err = wrmsr_on_cpu(cpu, MSR_K7_HWCR, l, h);
331	if (err)
332		pr_err("%s: error writing HWCR\n", __func__);
333
334	return err;
335}
336
337static int __set_inj(const char *buf)
338{
339	int i;
340
341	for (i = 0; i < N_INJ_TYPES; i++) {
342		if (!strncmp(flags_options[i], buf, strlen(flags_options[i]))) {
343			if (i > SW_INJ && !hw_injection_possible)
344				continue;
345			inj_type = i;
346			return 0;
347		}
348	}
349	return -EINVAL;
350}
351
352static ssize_t flags_read(struct file *filp, char __user *ubuf,
353			  size_t cnt, loff_t *ppos)
354{
355	char buf[MAX_FLAG_OPT_SIZE];
356	int n;
357
358	n = sprintf(buf, "%s\n", flags_options[inj_type]);
359
360	return simple_read_from_buffer(ubuf, cnt, ppos, buf, n);
361}
362
363static ssize_t flags_write(struct file *filp, const char __user *ubuf,
364			   size_t cnt, loff_t *ppos)
365{
366	char buf[MAX_FLAG_OPT_SIZE], *__buf;
367	int err;
368
369	if (!cnt || cnt > MAX_FLAG_OPT_SIZE)
370		return -EINVAL;
371
372	if (copy_from_user(&buf, ubuf, cnt))
373		return -EFAULT;
374
375	buf[cnt - 1] = 0;
376
377	/* strip whitespace */
378	__buf = strstrip(buf);
379
380	err = __set_inj(__buf);
381	if (err) {
382		pr_err("%s: Invalid flags value: %s\n", __func__, __buf);
383		return err;
384	}
385
386	*ppos += cnt;
387
388	return cnt;
389}
390
391static const struct file_operations flags_fops = {
392	.read           = flags_read,
393	.write          = flags_write,
394	.llseek         = generic_file_llseek,
395};
396
397/*
398 * On which CPU to inject?
399 */
400MCE_INJECT_GET(extcpu);
401
402static int inj_extcpu_set(void *data, u64 val)
403{
404	struct mce *m = (struct mce *)data;
405
406	if (val >= nr_cpu_ids || !cpu_online(val)) {
407		pr_err("%s: Invalid CPU: %llu\n", __func__, val);
408		return -EINVAL;
409	}
410	m->extcpu = val;
411	return 0;
412}
413
414DEFINE_SIMPLE_ATTRIBUTE(extcpu_fops, inj_extcpu_get, inj_extcpu_set, "%llu\n");
415
416static void trigger_mce(void *info)
417{
418	asm volatile("int $18");
419}
420
421static void trigger_dfr_int(void *info)
422{
423	asm volatile("int %0" :: "i" (DEFERRED_ERROR_VECTOR));
424}
425
426static void trigger_thr_int(void *info)
427{
428	asm volatile("int %0" :: "i" (THRESHOLD_APIC_VECTOR));
429}
430
431static u32 get_nbc_for_node(int node_id)
432{
433	u32 cores_per_node;
434
435	cores_per_node = topology_num_threads_per_package() / topology_amd_nodes_per_pkg();
436	return cores_per_node * node_id;
437}
438
439static void toggle_nb_mca_mst_cpu(u16 nid)
440{
441	struct amd_northbridge *nb;
442	struct pci_dev *F3;
443	u32 val;
444	int err;
445
446	nb = node_to_amd_nb(nid);
447	if (!nb)
448		return;
449
450	F3 = nb->misc;
451	if (!F3)
452		return;
453
454	err = pci_read_config_dword(F3, NBCFG, &val);
455	if (err) {
456		pr_err("%s: Error reading F%dx%03x.\n",
457		       __func__, PCI_FUNC(F3->devfn), NBCFG);
458		return;
459	}
460
461	if (val & BIT(27))
462		return;
463
464	pr_err("%s: Set D18F3x44[NbMcaToMstCpuEn] which BIOS hasn't done.\n",
465	       __func__);
466
467	val |= BIT(27);
468	err = pci_write_config_dword(F3, NBCFG, val);
469	if (err)
470		pr_err("%s: Error writing F%dx%03x.\n",
471		       __func__, PCI_FUNC(F3->devfn), NBCFG);
472}
473
474static void prepare_msrs(void *info)
475{
476	struct mce m = *(struct mce *)info;
477	u8 b = m.bank;
478
479	wrmsrl(MSR_IA32_MCG_STATUS, m.mcgstatus);
480
481	if (boot_cpu_has(X86_FEATURE_SMCA)) {
482		if (m.inject_flags == DFR_INT_INJ) {
483			wrmsrl(MSR_AMD64_SMCA_MCx_DESTAT(b), m.status);
484			wrmsrl(MSR_AMD64_SMCA_MCx_DEADDR(b), m.addr);
485		} else {
486			wrmsrl(MSR_AMD64_SMCA_MCx_STATUS(b), m.status);
487			wrmsrl(MSR_AMD64_SMCA_MCx_ADDR(b), m.addr);
488		}
489
490		wrmsrl(MSR_AMD64_SMCA_MCx_MISC(b), m.misc);
491		wrmsrl(MSR_AMD64_SMCA_MCx_SYND(b), m.synd);
492	} else {
493		wrmsrl(MSR_IA32_MCx_STATUS(b), m.status);
494		wrmsrl(MSR_IA32_MCx_ADDR(b), m.addr);
495		wrmsrl(MSR_IA32_MCx_MISC(b), m.misc);
496	}
497}
498
499static void do_inject(void)
500{
501	u64 mcg_status = 0;
502	unsigned int cpu = i_mce.extcpu;
503	u8 b = i_mce.bank;
504
505	i_mce.tsc = rdtsc_ordered();
506
507	i_mce.status |= MCI_STATUS_VAL;
508
509	if (i_mce.misc)
510		i_mce.status |= MCI_STATUS_MISCV;
511
512	if (i_mce.synd)
513		i_mce.status |= MCI_STATUS_SYNDV;
514
515	if (inj_type == SW_INJ) {
516		mce_log(&i_mce);
517		return;
518	}
519
520	/* prep MCE global settings for the injection */
521	mcg_status = MCG_STATUS_MCIP | MCG_STATUS_EIPV;
522
523	if (!(i_mce.status & MCI_STATUS_PCC))
524		mcg_status |= MCG_STATUS_RIPV;
525
526	/*
527	 * Ensure necessary status bits for deferred errors:
528	 * - MCx_STATUS[Deferred]: make sure it is a deferred error
529	 * - MCx_STATUS[UC] cleared: deferred errors are _not_ UC
530	 */
531	if (inj_type == DFR_INT_INJ) {
532		i_mce.status |= MCI_STATUS_DEFERRED;
533		i_mce.status &= ~MCI_STATUS_UC;
534	}
535
536	/*
537	 * For multi node CPUs, logging and reporting of bank 4 errors happens
538	 * only on the node base core. Refer to D18F3x44[NbMcaToMstCpuEn] for
539	 * Fam10h and later BKDGs.
540	 */
541	if (boot_cpu_has(X86_FEATURE_AMD_DCM) &&
542	    b == 4 &&
543	    boot_cpu_data.x86 < 0x17) {
544		toggle_nb_mca_mst_cpu(topology_amd_node_id(cpu));
545		cpu = get_nbc_for_node(topology_amd_node_id(cpu));
546	}
547
548	cpus_read_lock();
549	if (!cpu_online(cpu))
550		goto err;
551
552	toggle_hw_mce_inject(cpu, true);
553
554	i_mce.mcgstatus = mcg_status;
555	i_mce.inject_flags = inj_type;
556	smp_call_function_single(cpu, prepare_msrs, &i_mce, 0);
557
558	toggle_hw_mce_inject(cpu, false);
559
560	switch (inj_type) {
561	case DFR_INT_INJ:
562		smp_call_function_single(cpu, trigger_dfr_int, NULL, 0);
563		break;
564	case THR_INT_INJ:
565		smp_call_function_single(cpu, trigger_thr_int, NULL, 0);
566		break;
567	default:
568		smp_call_function_single(cpu, trigger_mce, NULL, 0);
569	}
570
571err:
572	cpus_read_unlock();
573
574}
575
576/*
577 * This denotes into which bank we're injecting and triggers
578 * the injection, at the same time.
579 */
580static int inj_bank_set(void *data, u64 val)
581{
582	struct mce *m = (struct mce *)data;
583	u8 n_banks;
584	u64 cap;
585
586	/* Get bank count on target CPU so we can handle non-uniform values. */
587	rdmsrl_on_cpu(m->extcpu, MSR_IA32_MCG_CAP, &cap);
588	n_banks = cap & MCG_BANKCNT_MASK;
589
590	if (val >= n_banks) {
591		pr_err("MCA bank %llu non-existent on CPU%d\n", val, m->extcpu);
592		return -EINVAL;
593	}
594
595	m->bank = val;
596
597	/*
598	 * sw-only injection allows to write arbitrary values into the MCA
599	 * registers because it tests only the decoding paths.
600	 */
601	if (inj_type == SW_INJ)
602		goto inject;
603
604	/*
605	 * Read IPID value to determine if a bank is populated on the target
606	 * CPU.
607	 */
608	if (cpu_feature_enabled(X86_FEATURE_SMCA)) {
609		u64 ipid;
610
611		if (rdmsrl_on_cpu(m->extcpu, MSR_AMD64_SMCA_MCx_IPID(val), &ipid)) {
612			pr_err("Error reading IPID on CPU%d\n", m->extcpu);
613			return -EINVAL;
614		}
615
616		if (!ipid) {
617			pr_err("Cannot inject into unpopulated bank %llu\n", val);
618			return -ENODEV;
619		}
620	}
621
622inject:
623	do_inject();
624
625	/* Reset injection struct */
626	setup_inj_struct(&i_mce);
627
628	return 0;
629}
630
631MCE_INJECT_GET(bank);
632
633DEFINE_SIMPLE_ATTRIBUTE(bank_fops, inj_bank_get, inj_bank_set, "%llu\n");
634
635static const char readme_msg[] =
636"Description of the files and their usages:\n"
637"\n"
638"Note1: i refers to the bank number below.\n"
639"Note2: See respective BKDGs for the exact bit definitions of the files below\n"
640"as they mirror the hardware registers.\n"
641"\n"
642"status:\t Set MCi_STATUS: the bits in that MSR control the error type and\n"
643"\t attributes of the error which caused the MCE.\n"
644"\n"
645"misc:\t Set MCi_MISC: provide auxiliary info about the error. It is mostly\n"
646"\t used for error thresholding purposes and its validity is indicated by\n"
647"\t MCi_STATUS[MiscV].\n"
648"\n"
649"synd:\t Set MCi_SYND: provide syndrome info about the error. Only valid on\n"
650"\t Scalable MCA systems, and its validity is indicated by MCi_STATUS[SyndV].\n"
651"\n"
652"addr:\t Error address value to be written to MCi_ADDR. Log address information\n"
653"\t associated with the error.\n"
654"\n"
655"cpu:\t The CPU to inject the error on.\n"
656"\n"
657"bank:\t Specify the bank you want to inject the error into: the number of\n"
658"\t banks in a processor varies and is family/model-specific, therefore, the\n"
659"\t supplied value is sanity-checked. Setting the bank value also triggers the\n"
660"\t injection.\n"
661"\n"
662"flags:\t Injection type to be performed. Writing to this file will trigger a\n"
663"\t real machine check, an APIC interrupt or invoke the error decoder routines\n"
664"\t for AMD processors.\n"
665"\n"
666"\t Allowed error injection types:\n"
667"\t  - \"sw\": Software error injection. Decode error to a human-readable \n"
668"\t    format only. Safe to use.\n"
669"\t  - \"hw\": Hardware error injection. Causes the #MC exception handler to \n"
670"\t    handle the error. Be warned: might cause system panic if MCi_STATUS[PCC] \n"
671"\t    is set. Therefore, consider setting (debugfs_mountpoint)/mce/fake_panic \n"
672"\t    before injecting.\n"
673"\t  - \"df\": Trigger APIC interrupt for Deferred error. Causes deferred \n"
674"\t    error APIC interrupt handler to handle the error if the feature is \n"
675"\t    is present in hardware. \n"
676"\t  - \"th\": Trigger APIC interrupt for Threshold errors. Causes threshold \n"
677"\t    APIC interrupt handler to handle the error. \n"
678"\n"
679"ipid:\t IPID (AMD-specific)\n"
680"\n";
681
682static ssize_t
683inj_readme_read(struct file *filp, char __user *ubuf,
684		       size_t cnt, loff_t *ppos)
685{
686	return simple_read_from_buffer(ubuf, cnt, ppos,
687					readme_msg, strlen(readme_msg));
688}
689
690static const struct file_operations readme_fops = {
691	.read		= inj_readme_read,
692};
693
694static struct dfs_node {
695	char *name;
696	const struct file_operations *fops;
697	umode_t perm;
698} dfs_fls[] = {
699	{ .name = "status",	.fops = &status_fops, .perm = S_IRUSR | S_IWUSR },
700	{ .name = "misc",	.fops = &misc_fops,   .perm = S_IRUSR | S_IWUSR },
701	{ .name = "addr",	.fops = &addr_fops,   .perm = S_IRUSR | S_IWUSR },
702	{ .name = "synd",	.fops = &synd_fops,   .perm = S_IRUSR | S_IWUSR },
703	{ .name = "ipid",	.fops = &ipid_fops,   .perm = S_IRUSR | S_IWUSR },
704	{ .name = "bank",	.fops = &bank_fops,   .perm = S_IRUSR | S_IWUSR },
705	{ .name = "flags",	.fops = &flags_fops,  .perm = S_IRUSR | S_IWUSR },
706	{ .name = "cpu",	.fops = &extcpu_fops, .perm = S_IRUSR | S_IWUSR },
707	{ .name = "README",	.fops = &readme_fops, .perm = S_IRUSR | S_IRGRP | S_IROTH },
708};
709
710static void __init debugfs_init(void)
711{
712	unsigned int i;
713
714	dfs_inj = debugfs_create_dir("mce-inject", NULL);
715
716	for (i = 0; i < ARRAY_SIZE(dfs_fls); i++)
717		debugfs_create_file(dfs_fls[i].name, dfs_fls[i].perm, dfs_inj,
718				    &i_mce, dfs_fls[i].fops);
719}
720
721static void check_hw_inj_possible(void)
722{
723	int cpu;
724	u8 bank;
725
726	/*
727	 * This behavior exists only on SMCA systems though its not directly
728	 * related to SMCA.
729	 */
730	if (!cpu_feature_enabled(X86_FEATURE_SMCA))
731		return;
732
733	cpu = get_cpu();
734
735	for (bank = 0; bank < MAX_NR_BANKS; ++bank) {
736		u64 status = MCI_STATUS_VAL, ipid;
737
738		/* Check whether bank is populated */
739		rdmsrl(MSR_AMD64_SMCA_MCx_IPID(bank), ipid);
740		if (!ipid)
741			continue;
742
743		toggle_hw_mce_inject(cpu, true);
744
745		wrmsrl_safe(mca_msr_reg(bank, MCA_STATUS), status);
746		rdmsrl_safe(mca_msr_reg(bank, MCA_STATUS), &status);
747		wrmsrl_safe(mca_msr_reg(bank, MCA_STATUS), 0);
748
749		if (!status) {
750			hw_injection_possible = false;
751			pr_warn("Platform does not allow *hardware* error injection."
752				"Try using APEI EINJ instead.\n");
753		}
754
755		toggle_hw_mce_inject(cpu, false);
756
757		break;
758	}
759
760	put_cpu();
761}
762
763static int __init inject_init(void)
764{
765	if (!alloc_cpumask_var(&mce_inject_cpumask, GFP_KERNEL))
766		return -ENOMEM;
767
768	check_hw_inj_possible();
769
770	debugfs_init();
771
772	register_nmi_handler(NMI_LOCAL, mce_raise_notify, 0, "mce_notify");
773	mce_register_injector_chain(&inject_nb);
774
775	setup_inj_struct(&i_mce);
776
777	pr_info("Machine check injector initialized\n");
778
779	return 0;
780}
781
782static void __exit inject_exit(void)
783{
784
785	mce_unregister_injector_chain(&inject_nb);
786	unregister_nmi_handler(NMI_LOCAL, "mce_notify");
787
788	debugfs_remove_recursive(dfs_inj);
789	dfs_inj = NULL;
790
791	memset(&dfs_fls, 0, sizeof(dfs_fls));
792
793	free_cpumask_var(mce_inject_cpumask);
794}
795
796module_init(inject_init);
797module_exit(inject_exit);
798MODULE_LICENSE("GPL");
799