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