diff options
-rw-r--r-- | arch/x86/ras/Kconfig | 4 | ||||
-rw-r--r-- | arch/x86/ras/mce_amd_inj.c | 52 |
2 files changed, 53 insertions, 3 deletions
diff --git a/arch/x86/ras/Kconfig b/arch/x86/ras/Kconfig index 10fea5fc821e..df280da34825 100644 --- a/arch/x86/ras/Kconfig +++ b/arch/x86/ras/Kconfig | |||
@@ -1,11 +1,9 @@ | |||
1 | config AMD_MCE_INJ | 1 | config AMD_MCE_INJ |
2 | tristate "Simple MCE injection interface for AMD processors" | 2 | tristate "Simple MCE injection interface for AMD processors" |
3 | depends on RAS && EDAC_DECODE_MCE && DEBUG_FS | 3 | depends on RAS && EDAC_DECODE_MCE && DEBUG_FS && AMD_NB |
4 | default n | 4 | default n |
5 | help | 5 | help |
6 | This is a simple debugfs interface to inject MCEs and test different | 6 | This is a simple debugfs interface to inject MCEs and test different |
7 | aspects of the MCE handling code. | 7 | aspects of the MCE handling code. |
8 | 8 | ||
9 | WARNING: Do not even assume this interface is staying stable! | 9 | WARNING: Do not even assume this interface is staying stable! |
10 | |||
11 | |||
diff --git a/arch/x86/ras/mce_amd_inj.c b/arch/x86/ras/mce_amd_inj.c index 4d3bafb540c2..55d38cfa46c2 100644 --- a/arch/x86/ras/mce_amd_inj.c +++ b/arch/x86/ras/mce_amd_inj.c | |||
@@ -17,8 +17,10 @@ | |||
17 | #include <linux/cpu.h> | 17 | #include <linux/cpu.h> |
18 | #include <linux/string.h> | 18 | #include <linux/string.h> |
19 | #include <linux/uaccess.h> | 19 | #include <linux/uaccess.h> |
20 | #include <linux/pci.h> | ||
20 | 21 | ||
21 | #include <asm/mce.h> | 22 | #include <asm/mce.h> |
23 | #include <asm/amd_nb.h> | ||
22 | #include <asm/irq_vectors.h> | 24 | #include <asm/irq_vectors.h> |
23 | 25 | ||
24 | #include "../kernel/cpu/mcheck/mce-internal.h" | 26 | #include "../kernel/cpu/mcheck/mce-internal.h" |
@@ -32,6 +34,7 @@ static struct dentry *dfs_inj; | |||
32 | static u8 n_banks; | 34 | static u8 n_banks; |
33 | 35 | ||
34 | #define MAX_FLAG_OPT_SIZE 3 | 36 | #define MAX_FLAG_OPT_SIZE 3 |
37 | #define NBCFG 0x44 | ||
35 | 38 | ||
36 | enum injection_type { | 39 | enum injection_type { |
37 | SW_INJ = 0, /* SW injection, simply decode the error */ | 40 | SW_INJ = 0, /* SW injection, simply decode the error */ |
@@ -198,6 +201,45 @@ static void trigger_thr_int(void *info) | |||
198 | asm volatile("int %0" :: "i" (THRESHOLD_APIC_VECTOR)); | 201 | asm volatile("int %0" :: "i" (THRESHOLD_APIC_VECTOR)); |
199 | } | 202 | } |
200 | 203 | ||
204 | static u32 get_nbc_for_node(int node_id) | ||
205 | { | ||
206 | struct cpuinfo_x86 *c = &boot_cpu_data; | ||
207 | u32 cores_per_node; | ||
208 | |||
209 | cores_per_node = c->x86_max_cores / amd_get_nodes_per_socket(); | ||
210 | |||
211 | return cores_per_node * node_id; | ||
212 | } | ||
213 | |||
214 | static void toggle_nb_mca_mst_cpu(u16 nid) | ||
215 | { | ||
216 | struct pci_dev *F3 = node_to_amd_nb(nid)->misc; | ||
217 | u32 val; | ||
218 | int err; | ||
219 | |||
220 | if (!F3) | ||
221 | return; | ||
222 | |||
223 | err = pci_read_config_dword(F3, NBCFG, &val); | ||
224 | if (err) { | ||
225 | pr_err("%s: Error reading F%dx%03x.\n", | ||
226 | __func__, PCI_FUNC(F3->devfn), NBCFG); | ||
227 | return; | ||
228 | } | ||
229 | |||
230 | if (val & BIT(27)) | ||
231 | return; | ||
232 | |||
233 | pr_err("%s: Set D18F3x44[NbMcaToMstCpuEn] which BIOS hasn't done.\n", | ||
234 | __func__); | ||
235 | |||
236 | val |= BIT(27); | ||
237 | err = pci_write_config_dword(F3, NBCFG, val); | ||
238 | if (err) | ||
239 | pr_err("%s: Error writing F%dx%03x.\n", | ||
240 | __func__, PCI_FUNC(F3->devfn), NBCFG); | ||
241 | } | ||
242 | |||
201 | static void do_inject(void) | 243 | static void do_inject(void) |
202 | { | 244 | { |
203 | u64 mcg_status = 0; | 245 | u64 mcg_status = 0; |
@@ -228,6 +270,16 @@ static void do_inject(void) | |||
228 | i_mce.status |= (i_mce.status & ~MCI_STATUS_UC); | 270 | i_mce.status |= (i_mce.status & ~MCI_STATUS_UC); |
229 | } | 271 | } |
230 | 272 | ||
273 | /* | ||
274 | * For multi node CPUs, logging and reporting of bank 4 errors happens | ||
275 | * only on the node base core. Refer to D18F3x44[NbMcaToMstCpuEn] for | ||
276 | * Fam10h and later BKDGs. | ||
277 | */ | ||
278 | if (static_cpu_has(X86_FEATURE_AMD_DCM) && b == 4) { | ||
279 | toggle_nb_mca_mst_cpu(amd_get_nb_id(cpu)); | ||
280 | cpu = get_nbc_for_node(amd_get_nb_id(cpu)); | ||
281 | } | ||
282 | |||
231 | get_online_cpus(); | 283 | get_online_cpus(); |
232 | if (!cpu_online(cpu)) | 284 | if (!cpu_online(cpu)) |
233 | goto err; | 285 | goto err; |