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 static bool hw_injection_possible = true;
37
38 /*
39 * Collect all the MCi_XXX settings
40 */
41 static struct mce i_mce;
42 static struct dentry *dfs_inj;
43
44 #define MAX_FLAG_OPT_SIZE 4
45 #define NBCFG 0x44
46
47 enum 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
55 static 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 */
64 static enum injection_type inj_type = SW_INJ;
65
66 #define MCE_INJECT_SET(reg) \
67 static 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
75 MCE_INJECT_SET(status);
76 MCE_INJECT_SET(misc);
77 MCE_INJECT_SET(addr);
78 MCE_INJECT_SET(synd);
79
80 #define MCE_INJECT_GET(reg) \
81 static 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
89 MCE_INJECT_GET(status);
90 MCE_INJECT_GET(misc);
91 MCE_INJECT_GET(addr);
92 MCE_INJECT_GET(synd);
93 MCE_INJECT_GET(ipid);
94
95 DEFINE_SIMPLE_ATTRIBUTE(status_fops, inj_status_get, inj_status_set, "%llx\n");
96 DEFINE_SIMPLE_ATTRIBUTE(misc_fops, inj_misc_get, inj_misc_set, "%llx\n");
97 DEFINE_SIMPLE_ATTRIBUTE(addr_fops, inj_addr_get, inj_addr_set, "%llx\n");
98 DEFINE_SIMPLE_ATTRIBUTE(synd_fops, inj_synd_get, inj_synd_set, "%llx\n");
99
100 /* Use the user provided IPID value on a sw injection. */
inj_ipid_set(void * data,u64 val)101 static 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
113 DEFINE_SIMPLE_ATTRIBUTE(ipid_fops, inj_ipid_get, inj_ipid_set, "%llx\n");
114
setup_inj_struct(struct mce * m)115 static 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. */
inject_mce(struct mce * m)126 static 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
raise_poll(struct mce * m)144 static 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
raise_exception(struct mce * m,struct pt_regs * pregs)156 static 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(®s, 0, sizeof(struct pt_regs));
163 regs.ip = m->ip;
164 regs.cs = m->cs;
165 pregs = ®s;
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
174 static cpumask_var_t mce_inject_cpumask;
175 static DEFINE_MUTEX(mce_inject_mutex);
176
mce_raise_notify(unsigned int cmd,struct pt_regs * regs)177 static 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
mce_irq_ipi(void * info)191 static 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 */
raise_local(void)204 static 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
raise_mce(struct mce * m)240 static 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,
274 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
mce_inject_raise(struct notifier_block * nb,unsigned long val,void * data)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 */
toggle_hw_mce_inject(unsigned int cpu,bool enable)318 static int toggle_hw_mce_inject(unsigned int cpu, bool enable)
319 {
320 u32 l, h;
321 int err;
322
323 err = rdmsr_on_cpu(cpu, MSR_K7_HWCR, &l, &h);
324 if (err) {
325 pr_err("%s: error reading HWCR\n", __func__);
326 return err;
327 }
328
329 enable ? (l |= BIT(18)) : (l &= ~BIT(18));
330
331 err = wrmsr_on_cpu(cpu, MSR_K7_HWCR, l, h);
332 if (err)
333 pr_err("%s: error writing HWCR\n", __func__);
334
335 return err;
336 }
337
__set_inj(const char * buf)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
flags_read(struct file * filp,char __user * ubuf,size_t cnt,loff_t * ppos)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
flags_write(struct file * filp,const char __user * ubuf,size_t cnt,loff_t * ppos)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
inj_extcpu_set(void * data,u64 val)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
trigger_mce(void * info)417 static void trigger_mce(void *info)
418 {
419 asm volatile("int $18");
420 }
421
trigger_dfr_int(void * info)422 static void trigger_dfr_int(void *info)
423 {
424 asm volatile("int %0" :: "i" (DEFERRED_ERROR_VECTOR));
425 }
426
trigger_thr_int(void * info)427 static void trigger_thr_int(void *info)
428 {
429 asm volatile("int %0" :: "i" (THRESHOLD_APIC_VECTOR));
430 }
431
get_nbc_for_node(int node_id)432 static u32 get_nbc_for_node(int node_id)
433 {
434 struct cpuinfo_x86 *c = &boot_cpu_data;
435 u32 cores_per_node;
436
437 cores_per_node = (c->x86_max_cores * smp_num_siblings) / amd_get_nodes_per_socket();
438
439 return cores_per_node * node_id;
440 }
441
toggle_nb_mca_mst_cpu(u16 nid)442 static void toggle_nb_mca_mst_cpu(u16 nid)
443 {
444 struct amd_northbridge *nb;
445 struct pci_dev *F3;
446 u32 val;
447 int err;
448
449 nb = node_to_amd_nb(nid);
450 if (!nb)
451 return;
452
453 F3 = nb->misc;
454 if (!F3)
455 return;
456
457 err = pci_read_config_dword(F3, NBCFG, &val);
458 if (err) {
459 pr_err("%s: Error reading F%dx%03x.\n",
460 __func__, PCI_FUNC(F3->devfn), NBCFG);
461 return;
462 }
463
464 if (val & BIT(27))
465 return;
466
467 pr_err("%s: Set D18F3x44[NbMcaToMstCpuEn] which BIOS hasn't done.\n",
468 __func__);
469
470 val |= BIT(27);
471 err = pci_write_config_dword(F3, NBCFG, val);
472 if (err)
473 pr_err("%s: Error writing F%dx%03x.\n",
474 __func__, PCI_FUNC(F3->devfn), NBCFG);
475 }
476
prepare_msrs(void * info)477 static void prepare_msrs(void *info)
478 {
479 struct mce m = *(struct mce *)info;
480 u8 b = m.bank;
481
482 wrmsrl(MSR_IA32_MCG_STATUS, m.mcgstatus);
483
484 if (boot_cpu_has(X86_FEATURE_SMCA)) {
485 if (m.inject_flags == DFR_INT_INJ) {
486 wrmsrl(MSR_AMD64_SMCA_MCx_DESTAT(b), m.status);
487 wrmsrl(MSR_AMD64_SMCA_MCx_DEADDR(b), m.addr);
488 } else {
489 wrmsrl(MSR_AMD64_SMCA_MCx_STATUS(b), m.status);
490 wrmsrl(MSR_AMD64_SMCA_MCx_ADDR(b), m.addr);
491 }
492
493 wrmsrl(MSR_AMD64_SMCA_MCx_MISC(b), m.misc);
494 wrmsrl(MSR_AMD64_SMCA_MCx_SYND(b), m.synd);
495 } else {
496 wrmsrl(MSR_IA32_MCx_STATUS(b), m.status);
497 wrmsrl(MSR_IA32_MCx_ADDR(b), m.addr);
498 wrmsrl(MSR_IA32_MCx_MISC(b), m.misc);
499 }
500 }
501
do_inject(void)502 static void do_inject(void)
503 {
504 u64 mcg_status = 0;
505 unsigned int cpu = i_mce.extcpu;
506 u8 b = i_mce.bank;
507
508 i_mce.tsc = rdtsc_ordered();
509
510 i_mce.status |= MCI_STATUS_VAL;
511
512 if (i_mce.misc)
513 i_mce.status |= MCI_STATUS_MISCV;
514
515 if (i_mce.synd)
516 i_mce.status |= MCI_STATUS_SYNDV;
517
518 if (inj_type == SW_INJ) {
519 mce_log(&i_mce);
520 return;
521 }
522
523 /* prep MCE global settings for the injection */
524 mcg_status = MCG_STATUS_MCIP | MCG_STATUS_EIPV;
525
526 if (!(i_mce.status & MCI_STATUS_PCC))
527 mcg_status |= MCG_STATUS_RIPV;
528
529 /*
530 * Ensure necessary status bits for deferred errors:
531 * - MCx_STATUS[Deferred]: make sure it is a deferred error
532 * - MCx_STATUS[UC] cleared: deferred errors are _not_ UC
533 */
534 if (inj_type == DFR_INT_INJ) {
535 i_mce.status |= MCI_STATUS_DEFERRED;
536 i_mce.status &= ~MCI_STATUS_UC;
537 }
538
539 /*
540 * For multi node CPUs, logging and reporting of bank 4 errors happens
541 * only on the node base core. Refer to D18F3x44[NbMcaToMstCpuEn] for
542 * Fam10h and later BKDGs.
543 */
544 if (boot_cpu_has(X86_FEATURE_AMD_DCM) &&
545 b == 4 &&
546 boot_cpu_data.x86 < 0x17) {
547 toggle_nb_mca_mst_cpu(topology_die_id(cpu));
548 cpu = get_nbc_for_node(topology_die_id(cpu));
549 }
550
551 cpus_read_lock();
552 if (!cpu_online(cpu))
553 goto err;
554
555 toggle_hw_mce_inject(cpu, true);
556
557 i_mce.mcgstatus = mcg_status;
558 i_mce.inject_flags = inj_type;
559 smp_call_function_single(cpu, prepare_msrs, &i_mce, 0);
560
561 toggle_hw_mce_inject(cpu, false);
562
563 switch (inj_type) {
564 case DFR_INT_INJ:
565 smp_call_function_single(cpu, trigger_dfr_int, NULL, 0);
566 break;
567 case THR_INT_INJ:
568 smp_call_function_single(cpu, trigger_thr_int, NULL, 0);
569 break;
570 default:
571 smp_call_function_single(cpu, trigger_mce, NULL, 0);
572 }
573
574 err:
575 cpus_read_unlock();
576
577 }
578
579 /*
580 * This denotes into which bank we're injecting and triggers
581 * the injection, at the same time.
582 */
inj_bank_set(void * data,u64 val)583 static int inj_bank_set(void *data, u64 val)
584 {
585 struct mce *m = (struct mce *)data;
586 u8 n_banks;
587 u64 cap;
588
589 /* Get bank count on target CPU so we can handle non-uniform values. */
590 rdmsrl_on_cpu(m->extcpu, MSR_IA32_MCG_CAP, &cap);
591 n_banks = cap & MCG_BANKCNT_MASK;
592
593 if (val >= n_banks) {
594 pr_err("MCA bank %llu non-existent on CPU%d\n", val, m->extcpu);
595 return -EINVAL;
596 }
597
598 m->bank = val;
599
600 /*
601 * sw-only injection allows to write arbitrary values into the MCA
602 * registers because it tests only the decoding paths.
603 */
604 if (inj_type == SW_INJ)
605 goto inject;
606
607 /*
608 * Read IPID value to determine if a bank is populated on the target
609 * CPU.
610 */
611 if (cpu_feature_enabled(X86_FEATURE_SMCA)) {
612 u64 ipid;
613
614 if (rdmsrl_on_cpu(m->extcpu, MSR_AMD64_SMCA_MCx_IPID(val), &ipid)) {
615 pr_err("Error reading IPID on CPU%d\n", m->extcpu);
616 return -EINVAL;
617 }
618
619 if (!ipid) {
620 pr_err("Cannot inject into unpopulated bank %llu\n", val);
621 return -ENODEV;
622 }
623 }
624
625 inject:
626 do_inject();
627
628 /* Reset injection struct */
629 setup_inj_struct(&i_mce);
630
631 return 0;
632 }
633
634 MCE_INJECT_GET(bank);
635
636 DEFINE_SIMPLE_ATTRIBUTE(bank_fops, inj_bank_get, inj_bank_set, "%llu\n");
637
638 static const char readme_msg[] =
639 "Description of the files and their usages:\n"
640 "\n"
641 "Note1: i refers to the bank number below.\n"
642 "Note2: See respective BKDGs for the exact bit definitions of the files below\n"
643 "as they mirror the hardware registers.\n"
644 "\n"
645 "status:\t Set MCi_STATUS: the bits in that MSR control the error type and\n"
646 "\t attributes of the error which caused the MCE.\n"
647 "\n"
648 "misc:\t Set MCi_MISC: provide auxiliary info about the error. It is mostly\n"
649 "\t used for error thresholding purposes and its validity is indicated by\n"
650 "\t MCi_STATUS[MiscV].\n"
651 "\n"
652 "synd:\t Set MCi_SYND: provide syndrome info about the error. Only valid on\n"
653 "\t Scalable MCA systems, and its validity is indicated by MCi_STATUS[SyndV].\n"
654 "\n"
655 "addr:\t Error address value to be written to MCi_ADDR. Log address information\n"
656 "\t associated with the error.\n"
657 "\n"
658 "cpu:\t The CPU to inject the error on.\n"
659 "\n"
660 "bank:\t Specify the bank you want to inject the error into: the number of\n"
661 "\t banks in a processor varies and is family/model-specific, therefore, the\n"
662 "\t supplied value is sanity-checked. Setting the bank value also triggers the\n"
663 "\t injection.\n"
664 "\n"
665 "flags:\t Injection type to be performed. Writing to this file will trigger a\n"
666 "\t real machine check, an APIC interrupt or invoke the error decoder routines\n"
667 "\t for AMD processors.\n"
668 "\n"
669 "\t Allowed error injection types:\n"
670 "\t - \"sw\": Software error injection. Decode error to a human-readable \n"
671 "\t format only. Safe to use.\n"
672 "\t - \"hw\": Hardware error injection. Causes the #MC exception handler to \n"
673 "\t handle the error. Be warned: might cause system panic if MCi_STATUS[PCC] \n"
674 "\t is set. Therefore, consider setting (debugfs_mountpoint)/mce/fake_panic \n"
675 "\t before injecting.\n"
676 "\t - \"df\": Trigger APIC interrupt for Deferred error. Causes deferred \n"
677 "\t error APIC interrupt handler to handle the error if the feature is \n"
678 "\t is present in hardware. \n"
679 "\t - \"th\": Trigger APIC interrupt for Threshold errors. Causes threshold \n"
680 "\t APIC interrupt handler to handle the error. \n"
681 "\n"
682 "ipid:\t IPID (AMD-specific)\n"
683 "\n";
684
685 static ssize_t
inj_readme_read(struct file * filp,char __user * ubuf,size_t cnt,loff_t * ppos)686 inj_readme_read(struct file *filp, char __user *ubuf,
687 size_t cnt, loff_t *ppos)
688 {
689 return simple_read_from_buffer(ubuf, cnt, ppos,
690 readme_msg, strlen(readme_msg));
691 }
692
693 static const struct file_operations readme_fops = {
694 .read = inj_readme_read,
695 };
696
697 static struct dfs_node {
698 char *name;
699 const struct file_operations *fops;
700 umode_t perm;
701 } dfs_fls[] = {
702 { .name = "status", .fops = &status_fops, .perm = S_IRUSR | S_IWUSR },
703 { .name = "misc", .fops = &misc_fops, .perm = S_IRUSR | S_IWUSR },
704 { .name = "addr", .fops = &addr_fops, .perm = S_IRUSR | S_IWUSR },
705 { .name = "synd", .fops = &synd_fops, .perm = S_IRUSR | S_IWUSR },
706 { .name = "ipid", .fops = &ipid_fops, .perm = S_IRUSR | S_IWUSR },
707 { .name = "bank", .fops = &bank_fops, .perm = S_IRUSR | S_IWUSR },
708 { .name = "flags", .fops = &flags_fops, .perm = S_IRUSR | S_IWUSR },
709 { .name = "cpu", .fops = &extcpu_fops, .perm = S_IRUSR | S_IWUSR },
710 { .name = "README", .fops = &readme_fops, .perm = S_IRUSR | S_IRGRP | S_IROTH },
711 };
712
debugfs_init(void)713 static void __init debugfs_init(void)
714 {
715 unsigned int i;
716
717 dfs_inj = debugfs_create_dir("mce-inject", NULL);
718
719 for (i = 0; i < ARRAY_SIZE(dfs_fls); i++)
720 debugfs_create_file(dfs_fls[i].name, dfs_fls[i].perm, dfs_inj,
721 &i_mce, dfs_fls[i].fops);
722 }
723
check_hw_inj_possible(void)724 static void check_hw_inj_possible(void)
725 {
726 int cpu;
727 u8 bank;
728
729 /*
730 * This behavior exists only on SMCA systems though its not directly
731 * related to SMCA.
732 */
733 if (!cpu_feature_enabled(X86_FEATURE_SMCA))
734 return;
735
736 cpu = get_cpu();
737
738 for (bank = 0; bank < MAX_NR_BANKS; ++bank) {
739 u64 status = MCI_STATUS_VAL, ipid;
740
741 /* Check whether bank is populated */
742 rdmsrl(MSR_AMD64_SMCA_MCx_IPID(bank), ipid);
743 if (!ipid)
744 continue;
745
746 toggle_hw_mce_inject(cpu, true);
747
748 wrmsrl_safe(mca_msr_reg(bank, MCA_STATUS), status);
749 rdmsrl_safe(mca_msr_reg(bank, MCA_STATUS), &status);
750
751 if (!status) {
752 hw_injection_possible = false;
753 pr_warn("Platform does not allow *hardware* error injection."
754 "Try using APEI EINJ instead.\n");
755 }
756
757 toggle_hw_mce_inject(cpu, false);
758
759 break;
760 }
761
762 put_cpu();
763 }
764
inject_init(void)765 static int __init inject_init(void)
766 {
767 if (!alloc_cpumask_var(&mce_inject_cpumask, GFP_KERNEL))
768 return -ENOMEM;
769
770 check_hw_inj_possible();
771
772 debugfs_init();
773
774 register_nmi_handler(NMI_LOCAL, mce_raise_notify, 0, "mce_notify");
775 mce_register_injector_chain(&inject_nb);
776
777 setup_inj_struct(&i_mce);
778
779 pr_info("Machine check injector initialized\n");
780
781 return 0;
782 }
783
inject_exit(void)784 static void __exit inject_exit(void)
785 {
786
787 mce_unregister_injector_chain(&inject_nb);
788 unregister_nmi_handler(NMI_LOCAL, "mce_notify");
789
790 debugfs_remove_recursive(dfs_inj);
791 dfs_inj = NULL;
792
793 memset(&dfs_fls, 0, sizeof(dfs_fls));
794
795 free_cpumask_var(mce_inject_cpumask);
796 }
797
798 module_init(inject_init);
799 module_exit(inject_exit);
800 MODULE_LICENSE("GPL");
801