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