1 // SPDX-License-Identifier: GPL-2.0-only
3 * Machine check injection support.
4 * Copyright 2008 Intel Corporation.
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
15 * Copyright (c) 2010-17: Borislav Petkov <bp@alien8.de>
16 * Advanced Micro Devices Inc.
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>
27 #include <asm/amd_nb.h>
29 #include <asm/irq_vectors.h>
36 static bool hw_injection_possible
= true;
39 * Collect all the MCi_XXX settings
41 static struct mce i_mce
;
42 static struct dentry
*dfs_inj
;
44 #define MAX_FLAG_OPT_SIZE 4
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 */
55 static const char * const flags_options
[] = {
63 /* Set default injection to SW_INJ */
64 static enum injection_type inj_type
= SW_INJ
;
66 #define MCE_INJECT_SET(reg) \
67 static int inj_##reg##_set(void *data, u64 val) \
69 struct mce *m = (struct mce *)data; \
75 MCE_INJECT_SET(status
);
80 #define MCE_INJECT_GET(reg) \
81 static int inj_##reg##_get(void *data, u64 *val) \
83 struct mce *m = (struct mce *)data; \
89 MCE_INJECT_GET(status
);
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");
100 /* Use the user provided IPID value on a sw injection. */
101 static int inj_ipid_set(void *data
, u64 val
)
103 struct mce
*m
= (struct mce
*)data
;
105 if (cpu_feature_enabled(X86_FEATURE_SMCA
)) {
106 if (inj_type
== SW_INJ
)
113 DEFINE_SIMPLE_ATTRIBUTE(ipid_fops
, inj_ipid_get
, inj_ipid_set
, "%llx\n");
115 static void setup_inj_struct(struct mce
*m
)
117 memset(m
, 0, sizeof(struct mce
));
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
;
125 /* Update fake mce registers on current CPU. */
126 static void inject_mce(struct mce
*m
)
128 struct mce
*i
= &per_cpu(injectm
, m
->extcpu
);
130 /* Make sure no one reads partially written injectm */
134 /* First set the fields after finished */
135 i
->extcpu
= m
->extcpu
;
137 /* Now write record in order, finished last (except above) */
138 memcpy(i
, m
, sizeof(struct mce
));
139 /* Finally activate it */
144 static void raise_poll(struct mce
*m
)
149 memset(&b
, 0xff, sizeof(mce_banks_t
));
150 local_irq_save(flags
);
151 machine_check_poll(0, &b
);
152 local_irq_restore(flags
);
156 static void raise_exception(struct mce
*m
, struct pt_regs
*pregs
)
162 memset(®s
, 0, sizeof(struct pt_regs
));
167 /* do_machine_check() expects interrupts disabled -- at least */
168 local_irq_save(flags
);
169 do_machine_check(pregs
);
170 local_irq_restore(flags
);
174 static cpumask_var_t mce_inject_cpumask
;
175 static DEFINE_MUTEX(mce_inject_mutex
);
177 static int mce_raise_notify(unsigned int cmd
, struct pt_regs
*regs
)
179 int cpu
= smp_processor_id();
180 struct mce
*m
= this_cpu_ptr(&injectm
);
181 if (!cpumask_test_cpu(cpu
, mce_inject_cpumask
))
183 cpumask_clear_cpu(cpu
, mce_inject_cpumask
);
184 if (m
->inject_flags
& MCJ_EXCEPTION
)
185 raise_exception(m
, regs
);
191 static void mce_irq_ipi(void *info
)
193 int cpu
= smp_processor_id();
194 struct mce
*m
= this_cpu_ptr(&injectm
);
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
);
203 /* Inject mce on current CPU */
204 static int raise_local(void)
206 struct mce
*m
= this_cpu_ptr(&injectm
);
207 int context
= MCJ_CTX(m
->inject_flags
);
211 if (m
->inject_flags
& MCJ_EXCEPTION
) {
212 pr_info("Triggering MCE exception on CPU %d\n", cpu
);
216 * Could do more to fake interrupts like
217 * calling irq_enter, but the necessary
218 * machinery isn't exported currently.
221 case MCJ_CTX_PROCESS
:
222 raise_exception(m
, NULL
);
225 pr_info("Invalid MCE context\n");
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
);
233 pr_info("Machine check poll done on CPU %d\n", cpu
);
240 static void __maybe_unused
raise_mce(struct mce
*m
)
242 int context
= MCJ_CTX(m
->inject_flags
);
246 if (context
== MCJ_CTX_RANDOM
)
249 if (m
->inject_flags
& (MCJ_IRQ_BROADCAST
| MCJ_NMI_BROADCAST
)) {
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
);
262 if (!cpumask_empty(mce_inject_cpumask
)) {
263 if (m
->inject_flags
& MCJ_IRQ_BROADCAST
) {
265 * don't wait because mce_irq_ipi is necessary
266 * to be sync with following raise_local
269 smp_call_function_many(mce_inject_cpumask
,
270 mce_irq_ipi
, NULL
, 0);
272 } else if (m
->inject_flags
& MCJ_NMI_BROADCAST
)
273 __apic_send_IPI_mask(mce_inject_cpumask
, NMI_VECTOR
);
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
));
294 static int mce_inject_raise(struct notifier_block
*nb
, unsigned long val
,
297 struct mce
*m
= (struct mce
*)data
;
302 mutex_lock(&mce_inject_mutex
);
304 mutex_unlock(&mce_inject_mutex
);
309 static struct notifier_block inject_nb
= {
310 .notifier_call
= mce_inject_raise
,
314 * Caller needs to be make sure this cpu doesn't disappear
315 * from under us, i.e.: get_cpu/put_cpu.
317 static int toggle_hw_mce_inject(unsigned int cpu
, bool enable
)
322 err
= rdmsr_on_cpu(cpu
, MSR_K7_HWCR
, &l
, &h
);
324 pr_err("%s: error reading HWCR\n", __func__
);
328 enable
? (l
|= BIT(18)) : (l
&= ~BIT(18));
330 err
= wrmsr_on_cpu(cpu
, MSR_K7_HWCR
, l
, h
);
332 pr_err("%s: error writing HWCR\n", __func__
);
337 static int __set_inj(const char *buf
)
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
)
352 static ssize_t
flags_read(struct file
*filp
, char __user
*ubuf
,
353 size_t cnt
, loff_t
*ppos
)
355 char buf
[MAX_FLAG_OPT_SIZE
];
358 n
= sprintf(buf
, "%s\n", flags_options
[inj_type
]);
360 return simple_read_from_buffer(ubuf
, cnt
, ppos
, buf
, n
);
363 static ssize_t
flags_write(struct file
*filp
, const char __user
*ubuf
,
364 size_t cnt
, loff_t
*ppos
)
366 char buf
[MAX_FLAG_OPT_SIZE
], *__buf
;
369 if (!cnt
|| cnt
> MAX_FLAG_OPT_SIZE
)
372 if (copy_from_user(&buf
, ubuf
, cnt
))
377 /* strip whitespace */
378 __buf
= strstrip(buf
);
380 err
= __set_inj(__buf
);
382 pr_err("%s: Invalid flags value: %s\n", __func__
, __buf
);
391 static const struct file_operations flags_fops
= {
393 .write
= flags_write
,
394 .llseek
= generic_file_llseek
,
398 * On which CPU to inject?
400 MCE_INJECT_GET(extcpu
);
402 static int inj_extcpu_set(void *data
, u64 val
)
404 struct mce
*m
= (struct mce
*)data
;
406 if (val
>= nr_cpu_ids
|| !cpu_online(val
)) {
407 pr_err("%s: Invalid CPU: %llu\n", __func__
, val
);
414 DEFINE_SIMPLE_ATTRIBUTE(extcpu_fops
, inj_extcpu_get
, inj_extcpu_set
, "%llu\n");
416 static void trigger_mce(void *info
)
418 asm volatile("int $18");
421 static void trigger_dfr_int(void *info
)
423 asm volatile("int %0" :: "i" (DEFERRED_ERROR_VECTOR
));
426 static void trigger_thr_int(void *info
)
428 asm volatile("int %0" :: "i" (THRESHOLD_APIC_VECTOR
));
431 static u32
get_nbc_for_node(int node_id
)
435 cores_per_node
= topology_num_threads_per_package() / topology_amd_nodes_per_pkg();
436 return cores_per_node
* node_id
;
439 static void toggle_nb_mca_mst_cpu(u16 nid
)
441 struct amd_northbridge
*nb
;
446 nb
= node_to_amd_nb(nid
);
454 err
= pci_read_config_dword(F3
, NBCFG
, &val
);
456 pr_err("%s: Error reading F%dx%03x.\n",
457 __func__
, PCI_FUNC(F3
->devfn
), NBCFG
);
464 pr_err("%s: Set D18F3x44[NbMcaToMstCpuEn] which BIOS hasn't done.\n",
468 err
= pci_write_config_dword(F3
, NBCFG
, val
);
470 pr_err("%s: Error writing F%dx%03x.\n",
471 __func__
, PCI_FUNC(F3
->devfn
), NBCFG
);
474 static void prepare_msrs(void *info
)
476 struct mce m
= *(struct mce
*)info
;
479 wrmsrl(MSR_IA32_MCG_STATUS
, m
.mcgstatus
);
481 if (boot_cpu_has(X86_FEATURE_SMCA
)) {
482 if (m
.inject_flags
== DFR_INT_INJ
) {
483 wrmsrl(MSR_AMD64_SMCA_MCx_DESTAT(b
), m
.status
);
484 wrmsrl(MSR_AMD64_SMCA_MCx_DEADDR(b
), m
.addr
);
486 wrmsrl(MSR_AMD64_SMCA_MCx_STATUS(b
), m
.status
);
487 wrmsrl(MSR_AMD64_SMCA_MCx_ADDR(b
), m
.addr
);
490 wrmsrl(MSR_AMD64_SMCA_MCx_SYND(b
), m
.synd
);
493 wrmsrl(MSR_AMD64_SMCA_MCx_MISC(b
), m
.misc
);
495 wrmsrl(MSR_IA32_MCx_STATUS(b
), m
.status
);
496 wrmsrl(MSR_IA32_MCx_ADDR(b
), m
.addr
);
499 wrmsrl(MSR_IA32_MCx_MISC(b
), m
.misc
);
503 static void do_inject(void)
506 unsigned int cpu
= i_mce
.extcpu
;
509 i_mce
.tsc
= rdtsc_ordered();
511 i_mce
.status
|= MCI_STATUS_VAL
;
514 i_mce
.status
|= MCI_STATUS_MISCV
;
517 i_mce
.status
|= MCI_STATUS_SYNDV
;
519 if (inj_type
== SW_INJ
) {
524 /* prep MCE global settings for the injection */
525 mcg_status
= MCG_STATUS_MCIP
| MCG_STATUS_EIPV
;
527 if (!(i_mce
.status
& MCI_STATUS_PCC
))
528 mcg_status
|= MCG_STATUS_RIPV
;
531 * Ensure necessary status bits for deferred errors:
532 * - MCx_STATUS[Deferred]: make sure it is a deferred error
533 * - MCx_STATUS[UC] cleared: deferred errors are _not_ UC
535 if (inj_type
== DFR_INT_INJ
) {
536 i_mce
.status
|= MCI_STATUS_DEFERRED
;
537 i_mce
.status
&= ~MCI_STATUS_UC
;
541 * For multi node CPUs, logging and reporting of bank 4 errors happens
542 * only on the node base core. Refer to D18F3x44[NbMcaToMstCpuEn] for
543 * Fam10h and later BKDGs.
545 if (boot_cpu_has(X86_FEATURE_AMD_DCM
) &&
547 boot_cpu_data
.x86
< 0x17) {
548 toggle_nb_mca_mst_cpu(topology_amd_node_id(cpu
));
549 cpu
= get_nbc_for_node(topology_amd_node_id(cpu
));
553 if (!cpu_online(cpu
))
556 toggle_hw_mce_inject(cpu
, true);
558 i_mce
.mcgstatus
= mcg_status
;
559 i_mce
.inject_flags
= inj_type
;
560 smp_call_function_single(cpu
, prepare_msrs
, &i_mce
, 0);
562 toggle_hw_mce_inject(cpu
, false);
566 smp_call_function_single(cpu
, trigger_dfr_int
, NULL
, 0);
569 smp_call_function_single(cpu
, trigger_thr_int
, NULL
, 0);
572 smp_call_function_single(cpu
, trigger_mce
, NULL
, 0);
581 * This denotes into which bank we're injecting and triggers
582 * the injection, at the same time.
584 static int inj_bank_set(void *data
, u64 val
)
586 struct mce
*m
= (struct mce
*)data
;
590 /* Get bank count on target CPU so we can handle non-uniform values. */
591 rdmsrl_on_cpu(m
->extcpu
, MSR_IA32_MCG_CAP
, &cap
);
592 n_banks
= cap
& MCG_BANKCNT_MASK
;
594 if (val
>= n_banks
) {
595 pr_err("MCA bank %llu non-existent on CPU%d\n", val
, m
->extcpu
);
602 * sw-only injection allows to write arbitrary values into the MCA
603 * registers because it tests only the decoding paths.
605 if (inj_type
== SW_INJ
)
609 * Read IPID value to determine if a bank is populated on the target
612 if (cpu_feature_enabled(X86_FEATURE_SMCA
)) {
615 if (rdmsrl_on_cpu(m
->extcpu
, MSR_AMD64_SMCA_MCx_IPID(val
), &ipid
)) {
616 pr_err("Error reading IPID on CPU%d\n", m
->extcpu
);
621 pr_err("Cannot inject into unpopulated bank %llu\n", val
);
629 /* Reset injection struct */
630 setup_inj_struct(&i_mce
);
635 MCE_INJECT_GET(bank
);
637 DEFINE_SIMPLE_ATTRIBUTE(bank_fops
, inj_bank_get
, inj_bank_set
, "%llu\n");
639 static const char readme_msg
[] =
640 "Description of the files and their usages:\n"
642 "Note1: i refers to the bank number below.\n"
643 "Note2: See respective BKDGs for the exact bit definitions of the files below\n"
644 "as they mirror the hardware registers.\n"
646 "status:\t Set MCi_STATUS: the bits in that MSR control the error type and\n"
647 "\t attributes of the error which caused the MCE.\n"
649 "misc:\t Set MCi_MISC: provide auxiliary info about the error. It is mostly\n"
650 "\t used for error thresholding purposes and its validity is indicated by\n"
651 "\t MCi_STATUS[MiscV].\n"
653 "synd:\t Set MCi_SYND: provide syndrome info about the error. Only valid on\n"
654 "\t Scalable MCA systems, and its validity is indicated by MCi_STATUS[SyndV].\n"
656 "addr:\t Error address value to be written to MCi_ADDR. Log address information\n"
657 "\t associated with the error.\n"
659 "cpu:\t The CPU to inject the error on.\n"
661 "bank:\t Specify the bank you want to inject the error into: the number of\n"
662 "\t banks in a processor varies and is family/model-specific, therefore, the\n"
663 "\t supplied value is sanity-checked. Setting the bank value also triggers the\n"
666 "flags:\t Injection type to be performed. Writing to this file will trigger a\n"
667 "\t real machine check, an APIC interrupt or invoke the error decoder routines\n"
668 "\t for AMD processors.\n"
670 "\t Allowed error injection types:\n"
671 "\t - \"sw\": Software error injection. Decode error to a human-readable \n"
672 "\t format only. Safe to use.\n"
673 "\t - \"hw\": Hardware error injection. Causes the #MC exception handler to \n"
674 "\t handle the error. Be warned: might cause system panic if MCi_STATUS[PCC] \n"
675 "\t is set. Therefore, consider setting (debugfs_mountpoint)/mce/fake_panic \n"
676 "\t before injecting.\n"
677 "\t - \"df\": Trigger APIC interrupt for Deferred error. Causes deferred \n"
678 "\t error APIC interrupt handler to handle the error if the feature is \n"
679 "\t is present in hardware. \n"
680 "\t - \"th\": Trigger APIC interrupt for Threshold errors. Causes threshold \n"
681 "\t APIC interrupt handler to handle the error. \n"
683 "ipid:\t IPID (AMD-specific)\n"
687 inj_readme_read(struct file
*filp
, char __user
*ubuf
,
688 size_t cnt
, loff_t
*ppos
)
690 return simple_read_from_buffer(ubuf
, cnt
, ppos
,
691 readme_msg
, strlen(readme_msg
));
694 static const struct file_operations readme_fops
= {
695 .read
= inj_readme_read
,
698 static struct dfs_node
{
700 const struct file_operations
*fops
;
703 { .name
= "status", .fops
= &status_fops
, .perm
= S_IRUSR
| S_IWUSR
},
704 { .name
= "misc", .fops
= &misc_fops
, .perm
= S_IRUSR
| S_IWUSR
},
705 { .name
= "addr", .fops
= &addr_fops
, .perm
= S_IRUSR
| S_IWUSR
},
706 { .name
= "synd", .fops
= &synd_fops
, .perm
= S_IRUSR
| S_IWUSR
},
707 { .name
= "ipid", .fops
= &ipid_fops
, .perm
= S_IRUSR
| S_IWUSR
},
708 { .name
= "bank", .fops
= &bank_fops
, .perm
= S_IRUSR
| S_IWUSR
},
709 { .name
= "flags", .fops
= &flags_fops
, .perm
= S_IRUSR
| S_IWUSR
},
710 { .name
= "cpu", .fops
= &extcpu_fops
, .perm
= S_IRUSR
| S_IWUSR
},
711 { .name
= "README", .fops
= &readme_fops
, .perm
= S_IRUSR
| S_IRGRP
| S_IROTH
},
714 static void __init
debugfs_init(void)
718 dfs_inj
= debugfs_create_dir("mce-inject", NULL
);
720 for (i
= 0; i
< ARRAY_SIZE(dfs_fls
); i
++)
721 debugfs_create_file(dfs_fls
[i
].name
, dfs_fls
[i
].perm
, dfs_inj
,
722 &i_mce
, dfs_fls
[i
].fops
);
725 static void check_hw_inj_possible(void)
731 * This behavior exists only on SMCA systems though its not directly
734 if (!cpu_feature_enabled(X86_FEATURE_SMCA
))
739 for (bank
= 0; bank
< MAX_NR_BANKS
; ++bank
) {
740 u64 status
= MCI_STATUS_VAL
, ipid
;
742 /* Check whether bank is populated */
743 rdmsrl(MSR_AMD64_SMCA_MCx_IPID(bank
), ipid
);
747 toggle_hw_mce_inject(cpu
, true);
749 wrmsrl_safe(mca_msr_reg(bank
, MCA_STATUS
), status
);
750 rdmsrl_safe(mca_msr_reg(bank
, MCA_STATUS
), &status
);
751 wrmsrl_safe(mca_msr_reg(bank
, MCA_STATUS
), 0);
754 hw_injection_possible
= false;
755 pr_warn("Platform does not allow *hardware* error injection."
756 "Try using APEI EINJ instead.\n");
759 toggle_hw_mce_inject(cpu
, false);
767 static int __init
inject_init(void)
769 if (!alloc_cpumask_var(&mce_inject_cpumask
, GFP_KERNEL
))
772 check_hw_inj_possible();
776 register_nmi_handler(NMI_LOCAL
, mce_raise_notify
, 0, "mce_notify");
777 mce_register_injector_chain(&inject_nb
);
779 setup_inj_struct(&i_mce
);
781 pr_info("Machine check injector initialized\n");
786 static void __exit
inject_exit(void)
789 mce_unregister_injector_chain(&inject_nb
);
790 unregister_nmi_handler(NMI_LOCAL
, "mce_notify");
792 debugfs_remove_recursive(dfs_inj
);
795 memset(&dfs_fls
, 0, sizeof(dfs_fls
));
797 free_cpumask_var(mce_inject_cpumask
);
800 module_init(inject_init
);
801 module_exit(inject_exit
);
802 MODULE_DESCRIPTION("Machine check injection support");
803 MODULE_LICENSE("GPL");