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/msr.h>
32 #include <asm/nmi.h>
33 #include <asm/smp.h>
34
35 #include "internal.h"
36
37 static bool hw_injection_possible = true;
38
39 /*
40 * Collect all the MCi_XXX settings
41 */
42 static struct mce i_mce;
43 static struct dentry *dfs_inj;
44
45 #define MAX_FLAG_OPT_SIZE 4
46 #define NBCFG 0x44
47
48 enum injection_type {
49 SW_INJ = 0, /* SW injection, simply decode the error */
50 HW_INJ, /* Trigger a #MC */
51 DFR_INT_INJ, /* Trigger Deferred error interrupt */
52 THR_INT_INJ, /* Trigger threshold interrupt */
53 N_INJ_TYPES,
54 };
55
56 static const char * const flags_options[] = {
57 [SW_INJ] = "sw",
58 [HW_INJ] = "hw",
59 [DFR_INT_INJ] = "df",
60 [THR_INT_INJ] = "th",
61 NULL
62 };
63
64 /* Set default injection to SW_INJ */
65 static enum injection_type inj_type = SW_INJ;
66
67 #define MCE_INJECT_SET(reg) \
68 static int inj_##reg##_set(void *data, u64 val) \
69 { \
70 struct mce *m = (struct mce *)data; \
71 \
72 m->reg = val; \
73 return 0; \
74 }
75
76 MCE_INJECT_SET(status);
77 MCE_INJECT_SET(misc);
78 MCE_INJECT_SET(addr);
79 MCE_INJECT_SET(synd);
80
81 #define MCE_INJECT_GET(reg) \
82 static int inj_##reg##_get(void *data, u64 *val) \
83 { \
84 struct mce *m = (struct mce *)data; \
85 \
86 *val = m->reg; \
87 return 0; \
88 }
89
90 MCE_INJECT_GET(status);
91 MCE_INJECT_GET(misc);
92 MCE_INJECT_GET(addr);
93 MCE_INJECT_GET(synd);
94 MCE_INJECT_GET(ipid);
95
96 DEFINE_SIMPLE_ATTRIBUTE(status_fops, inj_status_get, inj_status_set, "%llx\n");
97 DEFINE_SIMPLE_ATTRIBUTE(misc_fops, inj_misc_get, inj_misc_set, "%llx\n");
98 DEFINE_SIMPLE_ATTRIBUTE(addr_fops, inj_addr_get, inj_addr_set, "%llx\n");
99 DEFINE_SIMPLE_ATTRIBUTE(synd_fops, inj_synd_get, inj_synd_set, "%llx\n");
100
101 /* Use the user provided IPID value on a sw injection. */
inj_ipid_set(void * data,u64 val)102 static int inj_ipid_set(void *data, u64 val)
103 {
104 struct mce *m = (struct mce *)data;
105
106 if (cpu_feature_enabled(X86_FEATURE_SMCA)) {
107 if (inj_type == SW_INJ)
108 m->ipid = val;
109 }
110
111 return 0;
112 }
113
114 DEFINE_SIMPLE_ATTRIBUTE(ipid_fops, inj_ipid_get, inj_ipid_set, "%llx\n");
115
setup_inj_struct(struct mce * m)116 static void setup_inj_struct(struct mce *m)
117 {
118 memset(m, 0, sizeof(struct mce));
119
120 m->cpuvendor = boot_cpu_data.x86_vendor;
121 m->time = ktime_get_real_seconds();
122 m->cpuid = cpuid_eax(1);
123 m->microcode = boot_cpu_data.microcode;
124 }
125
126 /* Update fake mce registers on current CPU. */
inject_mce(struct mce * m)127 static void inject_mce(struct mce *m)
128 {
129 struct mce *i = &per_cpu(injectm, m->extcpu);
130
131 /* Make sure no one reads partially written injectm */
132 i->finished = 0;
133 mb();
134 m->finished = 0;
135 /* First set the fields after finished */
136 i->extcpu = m->extcpu;
137 mb();
138 /* Now write record in order, finished last (except above) */
139 memcpy(i, m, sizeof(struct mce));
140 /* Finally activate it */
141 mb();
142 i->finished = 1;
143 }
144
raise_poll(struct mce * m)145 static void raise_poll(struct mce *m)
146 {
147 unsigned long flags;
148 mce_banks_t b;
149
150 memset(&b, 0xff, sizeof(mce_banks_t));
151 local_irq_save(flags);
152 machine_check_poll(0, &b);
153 local_irq_restore(flags);
154 m->finished = 0;
155 }
156
raise_exception(struct mce * m,struct pt_regs * pregs)157 static void raise_exception(struct mce *m, struct pt_regs *pregs)
158 {
159 struct pt_regs regs;
160 unsigned long flags;
161
162 if (!pregs) {
163 memset(®s, 0, sizeof(struct pt_regs));
164 regs.ip = m->ip;
165 regs.cs = m->cs;
166 pregs = ®s;
167 }
168 /* do_machine_check() expects interrupts disabled -- at least */
169 local_irq_save(flags);
170 do_machine_check(pregs);
171 local_irq_restore(flags);
172 m->finished = 0;
173 }
174
175 static cpumask_var_t mce_inject_cpumask;
176 static DEFINE_MUTEX(mce_inject_mutex);
177
mce_raise_notify(unsigned int cmd,struct pt_regs * regs)178 static int mce_raise_notify(unsigned int cmd, struct pt_regs *regs)
179 {
180 int cpu = smp_processor_id();
181 struct mce *m = this_cpu_ptr(&injectm);
182 if (!cpumask_test_cpu(cpu, mce_inject_cpumask))
183 return NMI_DONE;
184 cpumask_clear_cpu(cpu, mce_inject_cpumask);
185 if (m->inject_flags & MCJ_EXCEPTION)
186 raise_exception(m, regs);
187 else if (m->status)
188 raise_poll(m);
189 return NMI_HANDLED;
190 }
191
mce_irq_ipi(void * info)192 static void mce_irq_ipi(void *info)
193 {
194 int cpu = smp_processor_id();
195 struct mce *m = this_cpu_ptr(&injectm);
196
197 if (cpumask_test_cpu(cpu, mce_inject_cpumask) &&
198 m->inject_flags & MCJ_EXCEPTION) {
199 cpumask_clear_cpu(cpu, mce_inject_cpumask);
200 raise_exception(m, NULL);
201 }
202 }
203
204 /* Inject mce on current CPU */
raise_local(void)205 static int raise_local(void)
206 {
207 struct mce *m = this_cpu_ptr(&injectm);
208 int context = MCJ_CTX(m->inject_flags);
209 int ret = 0;
210 int cpu = m->extcpu;
211
212 if (m->inject_flags & MCJ_EXCEPTION) {
213 pr_info("Triggering MCE exception on CPU %d\n", cpu);
214 switch (context) {
215 case MCJ_CTX_IRQ:
216 /*
217 * Could do more to fake interrupts like
218 * calling irq_enter, but the necessary
219 * machinery isn't exported currently.
220 */
221 fallthrough;
222 case MCJ_CTX_PROCESS:
223 raise_exception(m, NULL);
224 break;
225 default:
226 pr_info("Invalid MCE context\n");
227 ret = -EINVAL;
228 }
229 pr_info("MCE exception done on CPU %d\n", cpu);
230 } else if (m->status) {
231 pr_info("Starting machine check poll CPU %d\n", cpu);
232 raise_poll(m);
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, 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
mce_inject_raise(struct notifier_block * nb,unsigned long val,void * data)294 static 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
309 static 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 */
toggle_hw_mce_inject(unsigned int cpu,bool enable)317 static 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
__set_inj(const char * buf)337 static 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
flags_read(struct file * filp,char __user * ubuf,size_t cnt,loff_t * ppos)352 static 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
flags_write(struct file * filp,const char __user * ubuf,size_t cnt,loff_t * ppos)363 static 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
391 static 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 */
400 MCE_INJECT_GET(extcpu);
401
inj_extcpu_set(void * data,u64 val)402 static 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
414 DEFINE_SIMPLE_ATTRIBUTE(extcpu_fops, inj_extcpu_get, inj_extcpu_set, "%llu\n");
415
trigger_mce(void * info)416 static void trigger_mce(void *info)
417 {
418 asm volatile("int $18");
419 }
420
trigger_dfr_int(void * info)421 static void trigger_dfr_int(void *info)
422 {
423 asm volatile("int %0" :: "i" (DEFERRED_ERROR_VECTOR));
424 }
425
trigger_thr_int(void * info)426 static void trigger_thr_int(void *info)
427 {
428 asm volatile("int %0" :: "i" (THRESHOLD_APIC_VECTOR));
429 }
430
get_nbc_for_node(int node_id)431 static 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
toggle_nb_mca_mst_cpu(u16 nid)439 static 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
prepare_msrs(void * info)474 static void prepare_msrs(void *info)
475 {
476 struct mce m = *(struct mce *)info;
477 u8 b = m.bank;
478
479 wrmsrq(MSR_IA32_MCG_STATUS, m.mcgstatus);
480
481 if (boot_cpu_has(X86_FEATURE_SMCA)) {
482 if (m.inject_flags == DFR_INT_INJ) {
483 wrmsrq(MSR_AMD64_SMCA_MCx_DESTAT(b), m.status);
484 wrmsrq(MSR_AMD64_SMCA_MCx_DEADDR(b), m.addr);
485 } else {
486 wrmsrq(MSR_AMD64_SMCA_MCx_STATUS(b), m.status);
487 wrmsrq(MSR_AMD64_SMCA_MCx_ADDR(b), m.addr);
488 }
489
490 wrmsrq(MSR_AMD64_SMCA_MCx_SYND(b), m.synd);
491
492 if (m.misc)
493 wrmsrq(MSR_AMD64_SMCA_MCx_MISC(b), m.misc);
494 } else {
495 wrmsrq(MSR_IA32_MCx_STATUS(b), m.status);
496 wrmsrq(MSR_IA32_MCx_ADDR(b), m.addr);
497
498 if (m.misc)
499 wrmsrq(MSR_IA32_MCx_MISC(b), m.misc);
500 }
501 }
502
do_inject(void)503 static void do_inject(void)
504 {
505 unsigned int cpu = i_mce.extcpu;
506 struct mce_hw_err err;
507 u64 mcg_status = 0;
508 u8 b = i_mce.bank;
509
510 i_mce.tsc = rdtsc_ordered();
511
512 i_mce.status |= MCI_STATUS_VAL;
513
514 if (i_mce.misc)
515 i_mce.status |= MCI_STATUS_MISCV;
516
517 if (i_mce.synd)
518 i_mce.status |= MCI_STATUS_SYNDV;
519
520 if (inj_type == SW_INJ) {
521 err.m = i_mce;
522 mce_log(&err);
523 return;
524 }
525
526 /* prep MCE global settings for the injection */
527 mcg_status = MCG_STATUS_MCIP | MCG_STATUS_EIPV;
528
529 if (!(i_mce.status & MCI_STATUS_PCC))
530 mcg_status |= MCG_STATUS_RIPV;
531
532 /*
533 * Ensure necessary status bits for deferred errors:
534 * - MCx_STATUS[Deferred]: make sure it is a deferred error
535 * - MCx_STATUS[UC] cleared: deferred errors are _not_ UC
536 */
537 if (inj_type == DFR_INT_INJ) {
538 i_mce.status |= MCI_STATUS_DEFERRED;
539 i_mce.status &= ~MCI_STATUS_UC;
540 }
541
542 /*
543 * For multi node CPUs, logging and reporting of bank 4 errors happens
544 * only on the node base core. Refer to D18F3x44[NbMcaToMstCpuEn] for
545 * Fam10h and later BKDGs.
546 */
547 if (boot_cpu_has(X86_FEATURE_AMD_DCM) &&
548 b == 4 &&
549 boot_cpu_data.x86 < 0x17) {
550 toggle_nb_mca_mst_cpu(topology_amd_node_id(cpu));
551 cpu = get_nbc_for_node(topology_amd_node_id(cpu));
552 }
553
554 cpus_read_lock();
555 if (!cpu_online(cpu))
556 goto err;
557
558 toggle_hw_mce_inject(cpu, true);
559
560 i_mce.mcgstatus = mcg_status;
561 i_mce.inject_flags = inj_type;
562 smp_call_function_single(cpu, prepare_msrs, &i_mce, 0);
563
564 toggle_hw_mce_inject(cpu, false);
565
566 switch (inj_type) {
567 case DFR_INT_INJ:
568 smp_call_function_single(cpu, trigger_dfr_int, NULL, 0);
569 break;
570 case THR_INT_INJ:
571 smp_call_function_single(cpu, trigger_thr_int, NULL, 0);
572 break;
573 default:
574 smp_call_function_single(cpu, trigger_mce, NULL, 0);
575 }
576
577 err:
578 cpus_read_unlock();
579
580 }
581
582 /*
583 * This denotes into which bank we're injecting and triggers
584 * the injection, at the same time.
585 */
inj_bank_set(void * data,u64 val)586 static int inj_bank_set(void *data, u64 val)
587 {
588 struct mce *m = (struct mce *)data;
589 u8 n_banks;
590 u64 cap;
591
592 /* Get bank count on target CPU so we can handle non-uniform values. */
593 rdmsrq_on_cpu(m->extcpu, MSR_IA32_MCG_CAP, &cap);
594 n_banks = cap & MCG_BANKCNT_MASK;
595
596 if (val >= n_banks) {
597 pr_err("MCA bank %llu non-existent on CPU%d\n", val, m->extcpu);
598 return -EINVAL;
599 }
600
601 m->bank = val;
602
603 /*
604 * sw-only injection allows to write arbitrary values into the MCA
605 * registers because it tests only the decoding paths.
606 */
607 if (inj_type == SW_INJ)
608 goto inject;
609
610 /*
611 * Read IPID value to determine if a bank is populated on the target
612 * CPU.
613 */
614 if (cpu_feature_enabled(X86_FEATURE_SMCA)) {
615 u64 ipid;
616
617 if (rdmsrq_on_cpu(m->extcpu, MSR_AMD64_SMCA_MCx_IPID(val), &ipid)) {
618 pr_err("Error reading IPID on CPU%d\n", m->extcpu);
619 return -EINVAL;
620 }
621
622 if (!ipid) {
623 pr_err("Cannot inject into unpopulated bank %llu\n", val);
624 return -ENODEV;
625 }
626 }
627
628 inject:
629 do_inject();
630
631 /* Reset injection struct */
632 setup_inj_struct(&i_mce);
633
634 return 0;
635 }
636
637 MCE_INJECT_GET(bank);
638
639 DEFINE_SIMPLE_ATTRIBUTE(bank_fops, inj_bank_get, inj_bank_set, "%llu\n");
640
641 static const char readme_msg[] =
642 "Description of the files and their usages:\n"
643 "\n"
644 "Note1: i refers to the bank number below.\n"
645 "Note2: See respective BKDGs for the exact bit definitions of the files below\n"
646 "as they mirror the hardware registers.\n"
647 "\n"
648 "status:\t Set MCi_STATUS: the bits in that MSR control the error type and\n"
649 "\t attributes of the error which caused the MCE.\n"
650 "\n"
651 "misc:\t Set MCi_MISC: provide auxiliary info about the error. It is mostly\n"
652 "\t used for error thresholding purposes and its validity is indicated by\n"
653 "\t MCi_STATUS[MiscV].\n"
654 "\n"
655 "synd:\t Set MCi_SYND: provide syndrome info about the error. Only valid on\n"
656 "\t Scalable MCA systems, and its validity is indicated by MCi_STATUS[SyndV].\n"
657 "\n"
658 "addr:\t Error address value to be written to MCi_ADDR. Log address information\n"
659 "\t associated with the error.\n"
660 "\n"
661 "cpu:\t The CPU to inject the error on.\n"
662 "\n"
663 "bank:\t Specify the bank you want to inject the error into: the number of\n"
664 "\t banks in a processor varies and is family/model-specific, therefore, the\n"
665 "\t supplied value is sanity-checked. Setting the bank value also triggers the\n"
666 "\t injection.\n"
667 "\n"
668 "flags:\t Injection type to be performed. Writing to this file will trigger a\n"
669 "\t real machine check, an APIC interrupt or invoke the error decoder routines\n"
670 "\t for AMD processors.\n"
671 "\n"
672 "\t Allowed error injection types:\n"
673 "\t - \"sw\": Software error injection. Decode error to a human-readable \n"
674 "\t format only. Safe to use.\n"
675 "\t - \"hw\": Hardware error injection. Causes the #MC exception handler to \n"
676 "\t handle the error. Be warned: might cause system panic if MCi_STATUS[PCC] \n"
677 "\t is set. Therefore, consider setting (debugfs_mountpoint)/mce/fake_panic \n"
678 "\t before injecting.\n"
679 "\t - \"df\": Trigger APIC interrupt for Deferred error. Causes deferred \n"
680 "\t error APIC interrupt handler to handle the error if the feature is \n"
681 "\t is present in hardware. \n"
682 "\t - \"th\": Trigger APIC interrupt for Threshold errors. Causes threshold \n"
683 "\t APIC interrupt handler to handle the error. \n"
684 "\n"
685 "ipid:\t IPID (AMD-specific)\n"
686 "\n";
687
688 static ssize_t
inj_readme_read(struct file * filp,char __user * ubuf,size_t cnt,loff_t * ppos)689 inj_readme_read(struct file *filp, char __user *ubuf,
690 size_t cnt, loff_t *ppos)
691 {
692 return simple_read_from_buffer(ubuf, cnt, ppos,
693 readme_msg, strlen(readme_msg));
694 }
695
696 static const struct file_operations readme_fops = {
697 .read = inj_readme_read,
698 };
699
700 static struct dfs_node {
701 char *name;
702 const struct file_operations *fops;
703 umode_t perm;
704 } dfs_fls[] = {
705 { .name = "status", .fops = &status_fops, .perm = S_IRUSR | S_IWUSR },
706 { .name = "misc", .fops = &misc_fops, .perm = S_IRUSR | S_IWUSR },
707 { .name = "addr", .fops = &addr_fops, .perm = S_IRUSR | S_IWUSR },
708 { .name = "synd", .fops = &synd_fops, .perm = S_IRUSR | S_IWUSR },
709 { .name = "ipid", .fops = &ipid_fops, .perm = S_IRUSR | S_IWUSR },
710 { .name = "bank", .fops = &bank_fops, .perm = S_IRUSR | S_IWUSR },
711 { .name = "flags", .fops = &flags_fops, .perm = S_IRUSR | S_IWUSR },
712 { .name = "cpu", .fops = &extcpu_fops, .perm = S_IRUSR | S_IWUSR },
713 { .name = "README", .fops = &readme_fops, .perm = S_IRUSR | S_IRGRP | S_IROTH },
714 };
715
debugfs_init(void)716 static void __init debugfs_init(void)
717 {
718 unsigned int i;
719
720 dfs_inj = debugfs_create_dir("mce-inject", NULL);
721
722 for (i = 0; i < ARRAY_SIZE(dfs_fls); i++)
723 debugfs_create_file(dfs_fls[i].name, dfs_fls[i].perm, dfs_inj,
724 &i_mce, dfs_fls[i].fops);
725 }
726
check_hw_inj_possible(void)727 static void check_hw_inj_possible(void)
728 {
729 int cpu;
730 u8 bank;
731
732 /*
733 * This behavior exists only on SMCA systems though its not directly
734 * related to SMCA.
735 */
736 if (!cpu_feature_enabled(X86_FEATURE_SMCA))
737 return;
738
739 cpu = get_cpu();
740
741 for (bank = 0; bank < MAX_NR_BANKS; ++bank) {
742 u64 status = MCI_STATUS_VAL, ipid;
743
744 /* Check whether bank is populated */
745 rdmsrq(MSR_AMD64_SMCA_MCx_IPID(bank), ipid);
746 if (!ipid)
747 continue;
748
749 toggle_hw_mce_inject(cpu, true);
750
751 wrmsrq_safe(mca_msr_reg(bank, MCA_STATUS), status);
752 rdmsrq_safe(mca_msr_reg(bank, MCA_STATUS), &status);
753 wrmsrq_safe(mca_msr_reg(bank, MCA_STATUS), 0);
754
755 if (!status) {
756 hw_injection_possible = false;
757 pr_warn("Platform does not allow *hardware* error injection."
758 "Try using APEI EINJ instead.\n");
759 }
760
761 toggle_hw_mce_inject(cpu, false);
762
763 break;
764 }
765
766 put_cpu();
767 }
768
inject_init(void)769 static int __init inject_init(void)
770 {
771 if (!alloc_cpumask_var(&mce_inject_cpumask, GFP_KERNEL))
772 return -ENOMEM;
773
774 check_hw_inj_possible();
775
776 debugfs_init();
777
778 register_nmi_handler(NMI_LOCAL, mce_raise_notify, 0, "mce_notify");
779 mce_register_injector_chain(&inject_nb);
780
781 setup_inj_struct(&i_mce);
782
783 pr_info("Machine check injector initialized\n");
784
785 return 0;
786 }
787
inject_exit(void)788 static void __exit inject_exit(void)
789 {
790
791 mce_unregister_injector_chain(&inject_nb);
792 unregister_nmi_handler(NMI_LOCAL, "mce_notify");
793
794 debugfs_remove_recursive(dfs_inj);
795 dfs_inj = NULL;
796
797 memset(&dfs_fls, 0, sizeof(dfs_fls));
798
799 free_cpumask_var(mce_inject_cpumask);
800 }
801
802 module_init(inject_init);
803 module_exit(inject_exit);
804 MODULE_DESCRIPTION("Machine check injection support");
805 MODULE_LICENSE("GPL");
806