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