Merge branch 'ras-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull RAS updates from Thomas Gleixner:
"The RAS updates for the 4.13 merge window:

- Cleanup of the MCE injection facility (Borsilav Petkov)

- Rework of the AMD/SMCA handling (Yazen Ghannam)

- Enhancements for ACPI/APEI to handle new notitication types (Shiju
Jose)

- atomic_t to refcount_t conversion (Elena Reshetova)

- A few fixes and enhancements all over the place"

* 'ras-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
RAS/CEC: Check the correct variable in the debugfs error handling
x86/mce: Always save severity in machine_check_poll()
x86/MCE, xen/mcelog: Make /dev/mcelog registration messages more precise
x86/mce: Update bootlog description to reflect behavior on AMD
x86/mce: Don't disable MCA banks when offlining a CPU on AMD
x86/mce/mce-inject: Preset the MCE injection struct
x86/mce: Clean up include files
x86/mce: Get rid of register_mce_write_callback()
x86/mce: Merge mce_amd_inj into mce-inject
x86/mce/AMD: Use saved threshold block info in interrupt handler
x86/mce/AMD: Use msr_stat when clearing MCA_STATUS
x86/mce/AMD: Carve out SMCA bank configuration
x86/mce/AMD: Redo error logging from APIC LVT interrupt handlers
x86/mce: Convert threshold_bank.cpus from atomic_t to refcount_t
RAS: Make local function parse_ras_param() static
ACPI/APEI: Handle GSIV and GPIO notification types

+773 -744
+2 -1
Documentation/x86/x86_64/boot-options.txt
··· 36 to broadcast MCEs. 37 mce=bootlog 38 Enable logging of machine checks left over from booting. 39 - Disabled by default on AMD because some BIOS leave bogus ones. 40 If your BIOS doesn't do that it's a good idea to enable though 41 to make sure you log even machine check events that result 42 in a reboot. On Intel systems it is enabled by default.
··· 36 to broadcast MCEs. 37 mce=bootlog 38 Enable logging of machine checks left over from booting. 39 + Disabled by default on AMD Fam10h and older because some BIOS 40 + leave bogus ones. 41 If your BIOS doesn't do that it's a good idea to enable though 42 to make sure you log even machine check events that result 43 in a reboot. On Intel systems it is enabled by default.
+1 -1
arch/x86/Kconfig
··· 1085 def_bool y 1086 1087 config X86_MCE_INJECT 1088 - depends on X86_MCE && X86_LOCAL_APIC && X86_MCELOG_LEGACY 1089 tristate "Machine check injector support" 1090 ---help--- 1091 Provide support for injecting machine checks for testing purposes.
··· 1085 def_bool y 1086 1087 config X86_MCE_INJECT 1088 + depends on X86_MCE && X86_LOCAL_APIC && DEBUG_FS 1089 tristate "Machine check injector support" 1090 ---help--- 1091 Provide support for injecting machine checks for testing purposes.
-2
arch/x86/Makefile
··· 257 258 drivers-$(CONFIG_FB) += arch/x86/video/ 259 260 - drivers-$(CONFIG_RAS) += arch/x86/ras/ 261 - 262 #### 263 # boot loader support. Several targets are kept for legacy purposes 264
··· 257 258 drivers-$(CONFIG_FB) += arch/x86/video/ 259 260 #### 261 # boot loader support. Several targets are kept for legacy purposes 262
+2 -1
arch/x86/include/asm/amd_nb.h
··· 3 4 #include <linux/ioport.h> 5 #include <linux/pci.h> 6 7 struct amd_nb_bus_dev_range { 8 u8 bus; ··· 56 struct threshold_block *blocks; 57 58 /* initialized to the number of CPUs on the node sharing this bank */ 59 - atomic_t cpus; 60 }; 61 62 struct amd_northbridge {
··· 3 4 #include <linux/ioport.h> 5 #include <linux/pci.h> 6 + #include <linux/refcount.h> 7 8 struct amd_nb_bus_dev_range { 9 u8 bus; ··· 55 struct threshold_block *blocks; 56 57 /* initialized to the number of CPUs on the node sharing this bank */ 58 + refcount_t cpus; 59 }; 60 61 struct amd_northbridge {
-4
arch/x86/include/asm/mce.h
··· 285 286 DECLARE_PER_CPU(struct mce, injectm); 287 288 - extern void register_mce_write_callback(ssize_t (*)(struct file *filp, 289 - const char __user *ubuf, 290 - size_t usize, loff_t *off)); 291 - 292 /* Disable CMCI/polling for MCA bank claimed by firmware */ 293 extern void mce_disable_bank(int bank); 294
··· 285 286 DECLARE_PER_CPU(struct mce, injectm); 287 288 /* Disable CMCI/polling for MCA bank claimed by firmware */ 289 extern void mce_disable_bank(int bank); 290
+5
arch/x86/include/asm/processor.h
··· 907 } 908 #endif /* CONFIG_X86_INTEL_MPX */ 909 910 extern u16 amd_get_nb_id(int cpu); 911 extern u32 amd_get_nodes_per_socket(void); 912 913 static inline uint32_t hypervisor_cpuid_base(const char *sig, uint32_t leaves) 914 {
··· 907 } 908 #endif /* CONFIG_X86_INTEL_MPX */ 909 910 + #ifdef CONFIG_CPU_SUP_AMD 911 extern u16 amd_get_nb_id(int cpu); 912 extern u32 amd_get_nodes_per_socket(void); 913 + #else 914 + static inline u16 amd_get_nb_id(int cpu) { return 0; } 915 + static inline u32 amd_get_nodes_per_socket(void) { return 0; } 916 + #endif 917 918 static inline uint32_t hypervisor_cpuid_base(const char *sig, uint32_t leaves) 919 {
+45 -12
arch/x86/kernel/cpu/mcheck/dev-mcelog.c
··· 17 18 #include "mce-internal.h" 19 20 static DEFINE_MUTEX(mce_chrdev_read_mutex); 21 22 static char mce_helper[128]; ··· 347 } 348 } 349 350 - static ssize_t (*mce_write)(struct file *filp, const char __user *ubuf, 351 - size_t usize, loff_t *off); 352 - 353 - void register_mce_write_callback(ssize_t (*fn)(struct file *filp, 354 - const char __user *ubuf, 355 - size_t usize, loff_t *off)) 356 { 357 - mce_write = fn; 358 } 359 - EXPORT_SYMBOL_GPL(register_mce_write_callback); 360 361 static ssize_t mce_chrdev_write(struct file *filp, const char __user *ubuf, 362 size_t usize, loff_t *off) 363 { 364 - if (mce_write) 365 - return mce_write(filp, ubuf, usize, off); 366 - else 367 return -EINVAL; 368 } 369 370 static const struct file_operations mce_chrdev_ops = { ··· 415 /* register character device /dev/mcelog */ 416 err = misc_register(&mce_chrdev_device); 417 if (err) { 418 - pr_err("Unable to init device /dev/mcelog (rc: %d)\n", err); 419 return err; 420 } 421 mce_register_decode_chain(&dev_mcelog_nb); 422 return 0; 423 }
··· 17 18 #include "mce-internal.h" 19 20 + static BLOCKING_NOTIFIER_HEAD(mce_injector_chain); 21 + 22 static DEFINE_MUTEX(mce_chrdev_read_mutex); 23 24 static char mce_helper[128]; ··· 345 } 346 } 347 348 + void mce_register_injector_chain(struct notifier_block *nb) 349 { 350 + blocking_notifier_chain_register(&mce_injector_chain, nb); 351 } 352 + EXPORT_SYMBOL_GPL(mce_register_injector_chain); 353 + 354 + void mce_unregister_injector_chain(struct notifier_block *nb) 355 + { 356 + blocking_notifier_chain_unregister(&mce_injector_chain, nb); 357 + } 358 + EXPORT_SYMBOL_GPL(mce_unregister_injector_chain); 359 360 static ssize_t mce_chrdev_write(struct file *filp, const char __user *ubuf, 361 size_t usize, loff_t *off) 362 { 363 + struct mce m; 364 + 365 + if (!capable(CAP_SYS_ADMIN)) 366 + return -EPERM; 367 + /* 368 + * There are some cases where real MSR reads could slip 369 + * through. 370 + */ 371 + if (!boot_cpu_has(X86_FEATURE_MCE) || !boot_cpu_has(X86_FEATURE_MCA)) 372 + return -EIO; 373 + 374 + if ((unsigned long)usize > sizeof(struct mce)) 375 + usize = sizeof(struct mce); 376 + if (copy_from_user(&m, ubuf, usize)) 377 + return -EFAULT; 378 + 379 + if (m.extcpu >= num_possible_cpus() || !cpu_online(m.extcpu)) 380 return -EINVAL; 381 + 382 + /* 383 + * Need to give user space some time to set everything up, 384 + * so do it a jiffie or two later everywhere. 385 + */ 386 + schedule_timeout(2); 387 + 388 + blocking_notifier_call_chain(&mce_injector_chain, 0, &m); 389 + 390 + return usize; 391 } 392 393 static const struct file_operations mce_chrdev_ops = { ··· 388 /* register character device /dev/mcelog */ 389 err = misc_register(&mce_chrdev_device); 390 if (err) { 391 + if (err == -EBUSY) 392 + /* Xen dom0 might have registered the device already. */ 393 + pr_info("Unable to init device /dev/mcelog, already registered"); 394 + else 395 + pr_err("Unable to init device /dev/mcelog (rc: %d)\n", err); 396 + 397 return err; 398 } 399 + 400 mce_register_decode_chain(&dev_mcelog_nb); 401 return 0; 402 }
+533 -52
arch/x86/kernel/cpu/mcheck/mce-inject.c
··· 10 * Authors: 11 * Andi Kleen 12 * Ying Huang 13 */ 14 - #include <linux/uaccess.h> 15 - #include <linux/module.h> 16 - #include <linux/timer.h> 17 - #include <linux/kernel.h> 18 - #include <linux/string.h> 19 - #include <linux/fs.h> 20 - #include <linux/preempt.h> 21 - #include <linux/smp.h> 22 - #include <linux/notifier.h> 23 - #include <linux/kdebug.h> 24 #include <linux/cpu.h> 25 - #include <linux/sched.h> 26 - #include <linux/gfp.h> 27 - #include <asm/mce.h> 28 #include <asm/apic.h> 29 #include <asm/nmi.h> 30 31 /* Update fake mce registers on current CPU. */ 32 static void inject_mce(struct mce *m) ··· 225 return ret; 226 } 227 228 - static void raise_mce(struct mce *m) 229 { 230 int context = MCJ_CTX(m->inject_flags); 231 ··· 280 } 281 } 282 283 - /* Error injection interface */ 284 - static ssize_t mce_write(struct file *filp, const char __user *ubuf, 285 - size_t usize, loff_t *off) 286 { 287 - struct mce m; 288 289 - if (!capable(CAP_SYS_ADMIN)) 290 - return -EPERM; 291 - /* 292 - * There are some cases where real MSR reads could slip 293 - * through. 294 - */ 295 - if (!boot_cpu_has(X86_FEATURE_MCE) || !boot_cpu_has(X86_FEATURE_MCA)) 296 - return -EIO; 297 - 298 - if ((unsigned long)usize > sizeof(struct mce)) 299 - usize = sizeof(struct mce); 300 - if (copy_from_user(&m, ubuf, usize)) 301 - return -EFAULT; 302 - 303 - if (m.extcpu >= num_possible_cpus() || !cpu_online(m.extcpu)) 304 - return -EINVAL; 305 - 306 - /* 307 - * Need to give user space some time to set everything up, 308 - * so do it a jiffie or two later everywhere. 309 - */ 310 - schedule_timeout(2); 311 312 mutex_lock(&mce_inject_mutex); 313 - raise_mce(&m); 314 mutex_unlock(&mce_inject_mutex); 315 - return usize; 316 } 317 318 - static int inject_init(void) 319 { 320 - if (!alloc_cpumask_var(&mce_inject_cpumask, GFP_KERNEL)) 321 - return -ENOMEM; 322 - pr_info("Machine check injector initialized\n"); 323 - register_mce_write_callback(mce_write); 324 - register_nmi_handler(NMI_LOCAL, mce_raise_notify, 0, 325 - "mce_notify"); 326 return 0; 327 } 328 329 - module_init(inject_init); 330 /* 331 - * Cannot tolerate unloading currently because we cannot 332 - * guarantee all openers of mce_chrdev will get a reference to us. 333 */ 334 MODULE_LICENSE("GPL");
··· 10 * Authors: 11 * Andi Kleen 12 * Ying Huang 13 + * 14 + * The AMD part (from mce_amd_inj.c): a simple MCE injection facility 15 + * for testing different aspects of the RAS code. This driver should be 16 + * built as module so that it can be loaded on production kernels for 17 + * testing purposes. 18 + * 19 + * This file may be distributed under the terms of the GNU General Public 20 + * License version 2. 21 + * 22 + * Copyright (c) 2010-17: Borislav Petkov <bp@alien8.de> 23 + * Advanced Micro Devices Inc. 24 */ 25 + 26 #include <linux/cpu.h> 27 + #include <linux/debugfs.h> 28 + #include <linux/kernel.h> 29 + #include <linux/module.h> 30 + #include <linux/notifier.h> 31 + #include <linux/pci.h> 32 + #include <linux/uaccess.h> 33 + 34 + #include <asm/amd_nb.h> 35 #include <asm/apic.h> 36 + #include <asm/irq_vectors.h> 37 + #include <asm/mce.h> 38 #include <asm/nmi.h> 39 + #include <asm/smp.h> 40 + 41 + #include "mce-internal.h" 42 + 43 + /* 44 + * Collect all the MCi_XXX settings 45 + */ 46 + static struct mce i_mce; 47 + static struct dentry *dfs_inj; 48 + 49 + static u8 n_banks; 50 + 51 + #define MAX_FLAG_OPT_SIZE 3 52 + #define NBCFG 0x44 53 + 54 + enum injection_type { 55 + SW_INJ = 0, /* SW injection, simply decode the error */ 56 + HW_INJ, /* Trigger a #MC */ 57 + DFR_INT_INJ, /* Trigger Deferred error interrupt */ 58 + THR_INT_INJ, /* Trigger threshold interrupt */ 59 + N_INJ_TYPES, 60 + }; 61 + 62 + static const char * const flags_options[] = { 63 + [SW_INJ] = "sw", 64 + [HW_INJ] = "hw", 65 + [DFR_INT_INJ] = "df", 66 + [THR_INT_INJ] = "th", 67 + NULL 68 + }; 69 + 70 + /* Set default injection to SW_INJ */ 71 + static enum injection_type inj_type = SW_INJ; 72 + 73 + #define MCE_INJECT_SET(reg) \ 74 + static int inj_##reg##_set(void *data, u64 val) \ 75 + { \ 76 + struct mce *m = (struct mce *)data; \ 77 + \ 78 + m->reg = val; \ 79 + return 0; \ 80 + } 81 + 82 + MCE_INJECT_SET(status); 83 + MCE_INJECT_SET(misc); 84 + MCE_INJECT_SET(addr); 85 + MCE_INJECT_SET(synd); 86 + 87 + #define MCE_INJECT_GET(reg) \ 88 + static int inj_##reg##_get(void *data, u64 *val) \ 89 + { \ 90 + struct mce *m = (struct mce *)data; \ 91 + \ 92 + *val = m->reg; \ 93 + return 0; \ 94 + } 95 + 96 + MCE_INJECT_GET(status); 97 + MCE_INJECT_GET(misc); 98 + MCE_INJECT_GET(addr); 99 + MCE_INJECT_GET(synd); 100 + 101 + DEFINE_SIMPLE_ATTRIBUTE(status_fops, inj_status_get, inj_status_set, "%llx\n"); 102 + DEFINE_SIMPLE_ATTRIBUTE(misc_fops, inj_misc_get, inj_misc_set, "%llx\n"); 103 + DEFINE_SIMPLE_ATTRIBUTE(addr_fops, inj_addr_get, inj_addr_set, "%llx\n"); 104 + DEFINE_SIMPLE_ATTRIBUTE(synd_fops, inj_synd_get, inj_synd_set, "%llx\n"); 105 + 106 + static void setup_inj_struct(struct mce *m) 107 + { 108 + memset(m, 0, sizeof(struct mce)); 109 + 110 + m->cpuvendor = boot_cpu_data.x86_vendor; 111 + } 112 113 /* Update fake mce registers on current CPU. */ 114 static void inject_mce(struct mce *m) ··· 143 return ret; 144 } 145 146 + static void __maybe_unused raise_mce(struct mce *m) 147 { 148 int context = MCJ_CTX(m->inject_flags); 149 ··· 198 } 199 } 200 201 + static int mce_inject_raise(struct notifier_block *nb, unsigned long val, 202 + void *data) 203 { 204 + struct mce *m = (struct mce *)data; 205 206 + if (!m) 207 + return NOTIFY_DONE; 208 209 mutex_lock(&mce_inject_mutex); 210 + raise_mce(m); 211 mutex_unlock(&mce_inject_mutex); 212 + 213 + return NOTIFY_DONE; 214 } 215 216 + static struct notifier_block inject_nb = { 217 + .notifier_call = mce_inject_raise, 218 + }; 219 + 220 + /* 221 + * Caller needs to be make sure this cpu doesn't disappear 222 + * from under us, i.e.: get_cpu/put_cpu. 223 + */ 224 + static int toggle_hw_mce_inject(unsigned int cpu, bool enable) 225 { 226 + u32 l, h; 227 + int err; 228 + 229 + err = rdmsr_on_cpu(cpu, MSR_K7_HWCR, &l, &h); 230 + if (err) { 231 + pr_err("%s: error reading HWCR\n", __func__); 232 + return err; 233 + } 234 + 235 + enable ? (l |= BIT(18)) : (l &= ~BIT(18)); 236 + 237 + err = wrmsr_on_cpu(cpu, MSR_K7_HWCR, l, h); 238 + if (err) 239 + pr_err("%s: error writing HWCR\n", __func__); 240 + 241 + return err; 242 + } 243 + 244 + static int __set_inj(const char *buf) 245 + { 246 + int i; 247 + 248 + for (i = 0; i < N_INJ_TYPES; i++) { 249 + if (!strncmp(flags_options[i], buf, strlen(flags_options[i]))) { 250 + inj_type = i; 251 + return 0; 252 + } 253 + } 254 + return -EINVAL; 255 + } 256 + 257 + static ssize_t flags_read(struct file *filp, char __user *ubuf, 258 + size_t cnt, loff_t *ppos) 259 + { 260 + char buf[MAX_FLAG_OPT_SIZE]; 261 + int n; 262 + 263 + n = sprintf(buf, "%s\n", flags_options[inj_type]); 264 + 265 + return simple_read_from_buffer(ubuf, cnt, ppos, buf, n); 266 + } 267 + 268 + static ssize_t flags_write(struct file *filp, const char __user *ubuf, 269 + size_t cnt, loff_t *ppos) 270 + { 271 + char buf[MAX_FLAG_OPT_SIZE], *__buf; 272 + int err; 273 + 274 + if (cnt > MAX_FLAG_OPT_SIZE) 275 + return -EINVAL; 276 + 277 + if (copy_from_user(&buf, ubuf, cnt)) 278 + return -EFAULT; 279 + 280 + buf[cnt - 1] = 0; 281 + 282 + /* strip whitespace */ 283 + __buf = strstrip(buf); 284 + 285 + err = __set_inj(__buf); 286 + if (err) { 287 + pr_err("%s: Invalid flags value: %s\n", __func__, __buf); 288 + return err; 289 + } 290 + 291 + *ppos += cnt; 292 + 293 + return cnt; 294 + } 295 + 296 + static const struct file_operations flags_fops = { 297 + .read = flags_read, 298 + .write = flags_write, 299 + .llseek = generic_file_llseek, 300 + }; 301 + 302 + /* 303 + * On which CPU to inject? 304 + */ 305 + MCE_INJECT_GET(extcpu); 306 + 307 + static int inj_extcpu_set(void *data, u64 val) 308 + { 309 + struct mce *m = (struct mce *)data; 310 + 311 + if (val >= nr_cpu_ids || !cpu_online(val)) { 312 + pr_err("%s: Invalid CPU: %llu\n", __func__, val); 313 + return -EINVAL; 314 + } 315 + m->extcpu = val; 316 return 0; 317 } 318 319 + DEFINE_SIMPLE_ATTRIBUTE(extcpu_fops, inj_extcpu_get, inj_extcpu_set, "%llu\n"); 320 + 321 + static void trigger_mce(void *info) 322 + { 323 + asm volatile("int $18"); 324 + } 325 + 326 + static void trigger_dfr_int(void *info) 327 + { 328 + asm volatile("int %0" :: "i" (DEFERRED_ERROR_VECTOR)); 329 + } 330 + 331 + static void trigger_thr_int(void *info) 332 + { 333 + asm volatile("int %0" :: "i" (THRESHOLD_APIC_VECTOR)); 334 + } 335 + 336 + static u32 get_nbc_for_node(int node_id) 337 + { 338 + struct cpuinfo_x86 *c = &boot_cpu_data; 339 + u32 cores_per_node; 340 + 341 + cores_per_node = (c->x86_max_cores * smp_num_siblings) / amd_get_nodes_per_socket(); 342 + 343 + return cores_per_node * node_id; 344 + } 345 + 346 + static void toggle_nb_mca_mst_cpu(u16 nid) 347 + { 348 + struct amd_northbridge *nb; 349 + struct pci_dev *F3; 350 + u32 val; 351 + int err; 352 + 353 + nb = node_to_amd_nb(nid); 354 + if (!nb) 355 + return; 356 + 357 + F3 = nb->misc; 358 + if (!F3) 359 + return; 360 + 361 + err = pci_read_config_dword(F3, NBCFG, &val); 362 + if (err) { 363 + pr_err("%s: Error reading F%dx%03x.\n", 364 + __func__, PCI_FUNC(F3->devfn), NBCFG); 365 + return; 366 + } 367 + 368 + if (val & BIT(27)) 369 + return; 370 + 371 + pr_err("%s: Set D18F3x44[NbMcaToMstCpuEn] which BIOS hasn't done.\n", 372 + __func__); 373 + 374 + val |= BIT(27); 375 + err = pci_write_config_dword(F3, NBCFG, val); 376 + if (err) 377 + pr_err("%s: Error writing F%dx%03x.\n", 378 + __func__, PCI_FUNC(F3->devfn), NBCFG); 379 + } 380 + 381 + static void prepare_msrs(void *info) 382 + { 383 + struct mce m = *(struct mce *)info; 384 + u8 b = m.bank; 385 + 386 + wrmsrl(MSR_IA32_MCG_STATUS, m.mcgstatus); 387 + 388 + if (boot_cpu_has(X86_FEATURE_SMCA)) { 389 + if (m.inject_flags == DFR_INT_INJ) { 390 + wrmsrl(MSR_AMD64_SMCA_MCx_DESTAT(b), m.status); 391 + wrmsrl(MSR_AMD64_SMCA_MCx_DEADDR(b), m.addr); 392 + } else { 393 + wrmsrl(MSR_AMD64_SMCA_MCx_STATUS(b), m.status); 394 + wrmsrl(MSR_AMD64_SMCA_MCx_ADDR(b), m.addr); 395 + } 396 + 397 + wrmsrl(MSR_AMD64_SMCA_MCx_MISC(b), m.misc); 398 + wrmsrl(MSR_AMD64_SMCA_MCx_SYND(b), m.synd); 399 + } else { 400 + wrmsrl(MSR_IA32_MCx_STATUS(b), m.status); 401 + wrmsrl(MSR_IA32_MCx_ADDR(b), m.addr); 402 + wrmsrl(MSR_IA32_MCx_MISC(b), m.misc); 403 + } 404 + } 405 + 406 + static void do_inject(void) 407 + { 408 + u64 mcg_status = 0; 409 + unsigned int cpu = i_mce.extcpu; 410 + u8 b = i_mce.bank; 411 + 412 + rdtscll(i_mce.tsc); 413 + 414 + if (i_mce.misc) 415 + i_mce.status |= MCI_STATUS_MISCV; 416 + 417 + if (i_mce.synd) 418 + i_mce.status |= MCI_STATUS_SYNDV; 419 + 420 + if (inj_type == SW_INJ) { 421 + mce_inject_log(&i_mce); 422 + return; 423 + } 424 + 425 + /* prep MCE global settings for the injection */ 426 + mcg_status = MCG_STATUS_MCIP | MCG_STATUS_EIPV; 427 + 428 + if (!(i_mce.status & MCI_STATUS_PCC)) 429 + mcg_status |= MCG_STATUS_RIPV; 430 + 431 + /* 432 + * Ensure necessary status bits for deferred errors: 433 + * - MCx_STATUS[Deferred]: make sure it is a deferred error 434 + * - MCx_STATUS[UC] cleared: deferred errors are _not_ UC 435 + */ 436 + if (inj_type == DFR_INT_INJ) { 437 + i_mce.status |= MCI_STATUS_DEFERRED; 438 + i_mce.status |= (i_mce.status & ~MCI_STATUS_UC); 439 + } 440 + 441 + /* 442 + * For multi node CPUs, logging and reporting of bank 4 errors happens 443 + * only on the node base core. Refer to D18F3x44[NbMcaToMstCpuEn] for 444 + * Fam10h and later BKDGs. 445 + */ 446 + if (static_cpu_has(X86_FEATURE_AMD_DCM) && 447 + b == 4 && 448 + boot_cpu_data.x86 < 0x17) { 449 + toggle_nb_mca_mst_cpu(amd_get_nb_id(cpu)); 450 + cpu = get_nbc_for_node(amd_get_nb_id(cpu)); 451 + } 452 + 453 + get_online_cpus(); 454 + if (!cpu_online(cpu)) 455 + goto err; 456 + 457 + toggle_hw_mce_inject(cpu, true); 458 + 459 + i_mce.mcgstatus = mcg_status; 460 + i_mce.inject_flags = inj_type; 461 + smp_call_function_single(cpu, prepare_msrs, &i_mce, 0); 462 + 463 + toggle_hw_mce_inject(cpu, false); 464 + 465 + switch (inj_type) { 466 + case DFR_INT_INJ: 467 + smp_call_function_single(cpu, trigger_dfr_int, NULL, 0); 468 + break; 469 + case THR_INT_INJ: 470 + smp_call_function_single(cpu, trigger_thr_int, NULL, 0); 471 + break; 472 + default: 473 + smp_call_function_single(cpu, trigger_mce, NULL, 0); 474 + } 475 + 476 + err: 477 + put_online_cpus(); 478 + 479 + } 480 + 481 /* 482 + * This denotes into which bank we're injecting and triggers 483 + * the injection, at the same time. 484 */ 485 + static int inj_bank_set(void *data, u64 val) 486 + { 487 + struct mce *m = (struct mce *)data; 488 + 489 + if (val >= n_banks) { 490 + pr_err("Non-existent MCE bank: %llu\n", val); 491 + return -EINVAL; 492 + } 493 + 494 + m->bank = val; 495 + do_inject(); 496 + 497 + return 0; 498 + } 499 + 500 + MCE_INJECT_GET(bank); 501 + 502 + DEFINE_SIMPLE_ATTRIBUTE(bank_fops, inj_bank_get, inj_bank_set, "%llu\n"); 503 + 504 + static const char readme_msg[] = 505 + "Description of the files and their usages:\n" 506 + "\n" 507 + "Note1: i refers to the bank number below.\n" 508 + "Note2: See respective BKDGs for the exact bit definitions of the files below\n" 509 + "as they mirror the hardware registers.\n" 510 + "\n" 511 + "status:\t Set MCi_STATUS: the bits in that MSR control the error type and\n" 512 + "\t attributes of the error which caused the MCE.\n" 513 + "\n" 514 + "misc:\t Set MCi_MISC: provide auxiliary info about the error. It is mostly\n" 515 + "\t used for error thresholding purposes and its validity is indicated by\n" 516 + "\t MCi_STATUS[MiscV].\n" 517 + "\n" 518 + "synd:\t Set MCi_SYND: provide syndrome info about the error. Only valid on\n" 519 + "\t Scalable MCA systems, and its validity is indicated by MCi_STATUS[SyndV].\n" 520 + "\n" 521 + "addr:\t Error address value to be written to MCi_ADDR. Log address information\n" 522 + "\t associated with the error.\n" 523 + "\n" 524 + "cpu:\t The CPU to inject the error on.\n" 525 + "\n" 526 + "bank:\t Specify the bank you want to inject the error into: the number of\n" 527 + "\t banks in a processor varies and is family/model-specific, therefore, the\n" 528 + "\t supplied value is sanity-checked. Setting the bank value also triggers the\n" 529 + "\t injection.\n" 530 + "\n" 531 + "flags:\t Injection type to be performed. Writing to this file will trigger a\n" 532 + "\t real machine check, an APIC interrupt or invoke the error decoder routines\n" 533 + "\t for AMD processors.\n" 534 + "\n" 535 + "\t Allowed error injection types:\n" 536 + "\t - \"sw\": Software error injection. Decode error to a human-readable \n" 537 + "\t format only. Safe to use.\n" 538 + "\t - \"hw\": Hardware error injection. Causes the #MC exception handler to \n" 539 + "\t handle the error. Be warned: might cause system panic if MCi_STATUS[PCC] \n" 540 + "\t is set. Therefore, consider setting (debugfs_mountpoint)/mce/fake_panic \n" 541 + "\t before injecting.\n" 542 + "\t - \"df\": Trigger APIC interrupt for Deferred error. Causes deferred \n" 543 + "\t error APIC interrupt handler to handle the error if the feature is \n" 544 + "\t is present in hardware. \n" 545 + "\t - \"th\": Trigger APIC interrupt for Threshold errors. Causes threshold \n" 546 + "\t APIC interrupt handler to handle the error. \n" 547 + "\n"; 548 + 549 + static ssize_t 550 + inj_readme_read(struct file *filp, char __user *ubuf, 551 + size_t cnt, loff_t *ppos) 552 + { 553 + return simple_read_from_buffer(ubuf, cnt, ppos, 554 + readme_msg, strlen(readme_msg)); 555 + } 556 + 557 + static const struct file_operations readme_fops = { 558 + .read = inj_readme_read, 559 + }; 560 + 561 + static struct dfs_node { 562 + char *name; 563 + struct dentry *d; 564 + const struct file_operations *fops; 565 + umode_t perm; 566 + } dfs_fls[] = { 567 + { .name = "status", .fops = &status_fops, .perm = S_IRUSR | S_IWUSR }, 568 + { .name = "misc", .fops = &misc_fops, .perm = S_IRUSR | S_IWUSR }, 569 + { .name = "addr", .fops = &addr_fops, .perm = S_IRUSR | S_IWUSR }, 570 + { .name = "synd", .fops = &synd_fops, .perm = S_IRUSR | S_IWUSR }, 571 + { .name = "bank", .fops = &bank_fops, .perm = S_IRUSR | S_IWUSR }, 572 + { .name = "flags", .fops = &flags_fops, .perm = S_IRUSR | S_IWUSR }, 573 + { .name = "cpu", .fops = &extcpu_fops, .perm = S_IRUSR | S_IWUSR }, 574 + { .name = "README", .fops = &readme_fops, .perm = S_IRUSR | S_IRGRP | S_IROTH }, 575 + }; 576 + 577 + static int __init debugfs_init(void) 578 + { 579 + unsigned int i; 580 + u64 cap; 581 + 582 + rdmsrl(MSR_IA32_MCG_CAP, cap); 583 + n_banks = cap & MCG_BANKCNT_MASK; 584 + 585 + dfs_inj = debugfs_create_dir("mce-inject", NULL); 586 + if (!dfs_inj) 587 + return -EINVAL; 588 + 589 + for (i = 0; i < ARRAY_SIZE(dfs_fls); i++) { 590 + dfs_fls[i].d = debugfs_create_file(dfs_fls[i].name, 591 + dfs_fls[i].perm, 592 + dfs_inj, 593 + &i_mce, 594 + dfs_fls[i].fops); 595 + 596 + if (!dfs_fls[i].d) 597 + goto err_dfs_add; 598 + } 599 + 600 + return 0; 601 + 602 + err_dfs_add: 603 + while (i-- > 0) 604 + debugfs_remove(dfs_fls[i].d); 605 + 606 + debugfs_remove(dfs_inj); 607 + dfs_inj = NULL; 608 + 609 + return -ENODEV; 610 + } 611 + 612 + static int __init inject_init(void) 613 + { 614 + int err; 615 + 616 + if (!alloc_cpumask_var(&mce_inject_cpumask, GFP_KERNEL)) 617 + return -ENOMEM; 618 + 619 + err = debugfs_init(); 620 + if (err) { 621 + free_cpumask_var(mce_inject_cpumask); 622 + return err; 623 + } 624 + 625 + register_nmi_handler(NMI_LOCAL, mce_raise_notify, 0, "mce_notify"); 626 + mce_register_injector_chain(&inject_nb); 627 + 628 + setup_inj_struct(&i_mce); 629 + 630 + pr_info("Machine check injector initialized\n"); 631 + 632 + return 0; 633 + } 634 + 635 + static void __exit inject_exit(void) 636 + { 637 + 638 + mce_unregister_injector_chain(&inject_nb); 639 + unregister_nmi_handler(NMI_LOCAL, "mce_notify"); 640 + 641 + debugfs_remove_recursive(dfs_inj); 642 + dfs_inj = NULL; 643 + 644 + memset(&dfs_fls, 0, sizeof(dfs_fls)); 645 + 646 + free_cpumask_var(mce_inject_cpumask); 647 + } 648 + 649 + module_init(inject_init); 650 + module_exit(inject_exit); 651 MODULE_LICENSE("GPL");
+5 -1
arch/x86/kernel/cpu/mcheck/mce-internal.h
··· 100 extern struct device_attribute dev_attr_trigger; 101 102 #ifdef CONFIG_X86_MCELOG_LEGACY 103 - extern void mce_work_trigger(void); 104 #else 105 static inline void mce_work_trigger(void) { } 106 #endif
··· 100 extern struct device_attribute dev_attr_trigger; 101 102 #ifdef CONFIG_X86_MCELOG_LEGACY 103 + void mce_work_trigger(void); 104 + void mce_register_injector_chain(struct notifier_block *nb); 105 + void mce_unregister_injector_chain(struct notifier_block *nb); 106 #else 107 static inline void mce_work_trigger(void) { } 108 + static inline void mce_register_injector_chain(struct notifier_block *nb) { } 109 + static inline void mce_unregister_injector_chain(struct notifier_block *nb) { } 110 #endif
+7 -10
arch/x86/kernel/cpu/mcheck/mce.c
··· 673 { 674 bool error_seen = false; 675 struct mce m; 676 - int severity; 677 int i; 678 679 this_cpu_inc(mce_poll_count); ··· 709 710 mce_read_aux(&m, i); 711 712 - severity = mce_severity(&m, mca_cfg.tolerant, NULL, false); 713 - 714 - if (severity == MCE_DEFERRED_SEVERITY && mce_is_memory_error(&m)) 715 - if (m.status & MCI_STATUS_ADDRV) 716 - m.severity = severity; 717 718 /* 719 * Don't get the IP here because it's unlikely to ··· 1545 */ 1546 clear_bit(10, (unsigned long *)&mce_banks[4].ctl); 1547 } 1548 - if (c->x86 < 17 && cfg->bootlog < 0) { 1549 /* 1550 * Lots of broken BIOS around that don't clear them 1551 * by default and leave crap in there. Don't log: ··· 1827 * mce=TOLERANCELEVEL[,monarchtimeout] (number, see above) 1828 * monarchtimeout is how long to wait for other CPUs on machine 1829 * check, or 0 to not wait 1830 - * mce=bootlog Log MCEs from before booting. Disabled by default on AMD. 1831 * mce=nobootlog Don't log MCEs from before booting. 1832 * mce=bios_cmci_threshold Don't program the CMCI threshold 1833 * mce=recovery force enable memcpy_mcsafe() ··· 1908 static void vendor_disable_error_reporting(void) 1909 { 1910 /* 1911 - * Don't clear on Intel CPUs. Some of these MSRs are socket-wide. 1912 * Disabling them for just a single offlined CPU is bad, since it will 1913 * inhibit reporting for all shared resources on the socket like the 1914 * last level cache (LLC), the integrated memory controller (iMC), etc. 1915 */ 1916 - if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) 1917 return; 1918 1919 mce_disable_error_reporting();
··· 673 { 674 bool error_seen = false; 675 struct mce m; 676 int i; 677 678 this_cpu_inc(mce_poll_count); ··· 710 711 mce_read_aux(&m, i); 712 713 + m.severity = mce_severity(&m, mca_cfg.tolerant, NULL, false); 714 715 /* 716 * Don't get the IP here because it's unlikely to ··· 1550 */ 1551 clear_bit(10, (unsigned long *)&mce_banks[4].ctl); 1552 } 1553 + if (c->x86 < 0x11 && cfg->bootlog < 0) { 1554 /* 1555 * Lots of broken BIOS around that don't clear them 1556 * by default and leave crap in there. Don't log: ··· 1832 * mce=TOLERANCELEVEL[,monarchtimeout] (number, see above) 1833 * monarchtimeout is how long to wait for other CPUs on machine 1834 * check, or 0 to not wait 1835 + * mce=bootlog Log MCEs from before booting. Disabled by default on AMD Fam10h 1836 + and older. 1837 * mce=nobootlog Don't log MCEs from before booting. 1838 * mce=bios_cmci_threshold Don't program the CMCI threshold 1839 * mce=recovery force enable memcpy_mcsafe() ··· 1912 static void vendor_disable_error_reporting(void) 1913 { 1914 /* 1915 + * Don't clear on Intel or AMD CPUs. Some of these MSRs are socket-wide. 1916 * Disabling them for just a single offlined CPU is bad, since it will 1917 * inhibit reporting for all shared resources on the socket like the 1918 * last level cache (LLC), the integrated memory controller (iMC), etc. 1919 */ 1920 + if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL || 1921 + boot_cpu_data.x86_vendor == X86_VENDOR_AMD) 1922 return; 1923 1924 mce_disable_error_reporting();
+144 -139
arch/x86/kernel/cpu/mcheck/mce_amd.c
··· 164 } 165 void (*deferred_error_int_vector)(void) = default_deferred_error_interrupt; 166 167 - static void get_smca_bank_info(unsigned int bank) 168 { 169 - unsigned int i, hwid_mcatype, cpu = smp_processor_id(); 170 struct smca_hwid *s_hwid; 171 - u32 high, instance_id; 172 173 /* Collect bank_info using CPU 0 for now. */ 174 if (cpu) 175 return; 176 177 - if (rdmsr_safe_on_cpu(cpu, MSR_AMD64_SMCA_MCx_IPID(bank), &instance_id, &high)) { 178 pr_warn("Failed to read MCA_IPID for bank %d\n", bank); 179 return; 180 } ··· 222 smca_get_name(s_hwid->bank_type)); 223 224 smca_banks[bank].hwid = s_hwid; 225 - smca_banks[bank].id = instance_id; 226 smca_banks[bank].sysfs_id = s_hwid->count++; 227 break; 228 } ··· 464 int offset, u32 misc_high) 465 { 466 unsigned int cpu = smp_processor_id(); 467 - u32 smca_low, smca_high, smca_addr; 468 struct threshold_block b; 469 int new; 470 ··· 486 if (!mce_flags.smca) { 487 new = (misc_high & MASK_LVTOFF_HI) >> 20; 488 goto set_offset; 489 - } 490 - 491 - smca_addr = MSR_AMD64_SMCA_MCx_CONFIG(bank); 492 - 493 - if (!rdmsr_safe(smca_addr, &smca_low, &smca_high)) { 494 - /* 495 - * OS is required to set the MCAX bit to acknowledge that it is 496 - * now using the new MSR ranges and new registers under each 497 - * bank. It also means that the OS will configure deferred 498 - * errors in the new MCx_CONFIG register. If the bit is not set, 499 - * uncorrectable errors will cause a system panic. 500 - * 501 - * MCA_CONFIG[MCAX] is bit 32 (0 in the high portion of the MSR.) 502 - */ 503 - smca_high |= BIT(0); 504 - 505 - /* 506 - * SMCA logs Deferred Error information in MCA_DE{STAT,ADDR} 507 - * registers with the option of additionally logging to 508 - * MCA_{STATUS,ADDR} if MCA_CONFIG[LogDeferredInMcaStat] is set. 509 - * 510 - * This bit is usually set by BIOS to retain the old behavior 511 - * for OSes that don't use the new registers. Linux supports the 512 - * new registers so let's disable that additional logging here. 513 - * 514 - * MCA_CONFIG[LogDeferredInMcaStat] is bit 34 (bit 2 in the high 515 - * portion of the MSR). 516 - */ 517 - smca_high &= ~BIT(2); 518 - 519 - /* 520 - * SMCA sets the Deferred Error Interrupt type per bank. 521 - * 522 - * MCA_CONFIG[DeferredIntTypeSupported] is bit 5, and tells us 523 - * if the DeferredIntType bit field is available. 524 - * 525 - * MCA_CONFIG[DeferredIntType] is bits [38:37] ([6:5] in the 526 - * high portion of the MSR). OS should set this to 0x1 to enable 527 - * APIC based interrupt. First, check that no interrupt has been 528 - * set. 529 - */ 530 - if ((smca_low & BIT(5)) && !((smca_high >> 5) & 0x3)) 531 - smca_high |= BIT(5); 532 - 533 - wrmsr(smca_addr, smca_low, smca_high); 534 } 535 536 /* Gather LVT offset for thresholding: */ ··· 516 517 for (bank = 0; bank < mca_cfg.banks; ++bank) { 518 if (mce_flags.smca) 519 - get_smca_bank_info(bank); 520 521 for (block = 0; block < NR_BLOCKS; ++block) { 522 address = get_block_address(cpu, address, low, high, bank, block); ··· 741 } 742 EXPORT_SYMBOL_GPL(umc_normaddr_to_sysaddr); 743 744 - static void 745 - __log_error(unsigned int bank, bool deferred_err, bool threshold_err, u64 misc) 746 { 747 - u32 msr_status = msr_ops.status(bank); 748 - u32 msr_addr = msr_ops.addr(bank); 749 struct mce m; 750 - u64 status; 751 - 752 - WARN_ON_ONCE(deferred_err && threshold_err); 753 - 754 - if (deferred_err && mce_flags.smca) { 755 - msr_status = MSR_AMD64_SMCA_MCx_DESTAT(bank); 756 - msr_addr = MSR_AMD64_SMCA_MCx_DEADDR(bank); 757 - } 758 - 759 - rdmsrl(msr_status, status); 760 - 761 - if (!(status & MCI_STATUS_VAL)) 762 - return; 763 764 mce_setup(&m); 765 766 m.status = status; 767 m.bank = bank; 768 m.tsc = rdtsc(); 769 770 - if (threshold_err) 771 - m.misc = misc; 772 - 773 if (m.status & MCI_STATUS_ADDRV) { 774 - rdmsrl(msr_addr, m.addr); 775 776 /* 777 * Extract [55:<lsb>] where lsb is the least significant ··· 774 } 775 776 mce_log(&m); 777 - 778 - wrmsrl(msr_status, 0); 779 } 780 781 static inline void __smp_deferred_error_interrupt(void) ··· 798 exiting_ack_irq(); 799 } 800 801 /* APIC interrupt handler for deferred errors */ 802 static void amd_deferred_error_interrupt(void) 803 { 804 unsigned int bank; 805 - u32 msr_status; 806 - u64 status; 807 808 - for (bank = 0; bank < mca_cfg.banks; ++bank) { 809 - msr_status = (mce_flags.smca) ? MSR_AMD64_SMCA_MCx_DESTAT(bank) 810 - : msr_ops.status(bank); 811 - 812 - rdmsrl(msr_status, status); 813 - 814 - if (!(status & MCI_STATUS_VAL) || 815 - !(status & MCI_STATUS_DEFERRED)) 816 - continue; 817 - 818 - __log_error(bank, true, false, 0); 819 - break; 820 - } 821 } 822 823 - /* 824 - * APIC Interrupt Handler 825 - */ 826 - 827 - /* 828 - * threshold interrupt handler will service THRESHOLD_APIC_VECTOR. 829 - * the interrupt goes off when error_count reaches threshold_limit. 830 - * the handler will simply log mcelog w/ software defined bank number. 831 - */ 832 - 833 - static void amd_threshold_interrupt(void) 834 { 835 - u32 low = 0, high = 0, address = 0; 836 - unsigned int bank, block, cpu = smp_processor_id(); 837 struct thresh_restart tr; 838 839 - /* assume first bank caused it */ 840 - for (bank = 0; bank < mca_cfg.banks; ++bank) { 841 - if (!(per_cpu(bank_map, cpu) & (1 << bank))) 842 - continue; 843 - for (block = 0; block < NR_BLOCKS; ++block) { 844 - address = get_block_address(cpu, address, low, high, bank, block); 845 - if (!address) 846 - break; 847 848 - if (rdmsr_safe(address, &low, &high)) 849 - break; 850 851 - if (!(high & MASK_VALID_HI)) { 852 - if (block) 853 - continue; 854 - else 855 - break; 856 - } 857 858 - if (!(high & MASK_CNTP_HI) || 859 - (high & MASK_LOCKED_HI)) 860 - continue; 861 - 862 - /* 863 - * Log the machine check that caused the threshold 864 - * event. 865 - */ 866 - if (high & MASK_OVERFLOW_HI) 867 - goto log; 868 - } 869 - } 870 - return; 871 - 872 - log: 873 - __log_error(bank, false, true, ((u64)high << 32) | low); 874 875 /* Reset threshold block after logging error. */ 876 memset(&tr, 0, sizeof(tr)); 877 - tr.b = &per_cpu(threshold_banks, cpu)[bank]->blocks[block]; 878 threshold_restart_bank(&tr); 879 } 880 881 /* ··· 1207 goto out; 1208 1209 per_cpu(threshold_banks, cpu)[bank] = b; 1210 - atomic_inc(&b->cpus); 1211 1212 err = __threshold_add_blocks(b); 1213 ··· 1230 per_cpu(threshold_banks, cpu)[bank] = b; 1231 1232 if (is_shared_bank(bank)) { 1233 - atomic_set(&b->cpus, 1); 1234 1235 /* nb is already initialized, see above */ 1236 if (nb) { ··· 1294 goto free_out; 1295 1296 if (is_shared_bank(bank)) { 1297 - if (!atomic_dec_and_test(&b->cpus)) { 1298 __threshold_remove_blocks(b); 1299 per_cpu(threshold_banks, cpu)[bank] = NULL; 1300 return;
··· 164 } 165 void (*deferred_error_int_vector)(void) = default_deferred_error_interrupt; 166 167 + static void smca_configure(unsigned int bank, unsigned int cpu) 168 { 169 + unsigned int i, hwid_mcatype; 170 struct smca_hwid *s_hwid; 171 + u32 high, low; 172 + u32 smca_config = MSR_AMD64_SMCA_MCx_CONFIG(bank); 173 + 174 + /* Set appropriate bits in MCA_CONFIG */ 175 + if (!rdmsr_safe(smca_config, &low, &high)) { 176 + /* 177 + * OS is required to set the MCAX bit to acknowledge that it is 178 + * now using the new MSR ranges and new registers under each 179 + * bank. It also means that the OS will configure deferred 180 + * errors in the new MCx_CONFIG register. If the bit is not set, 181 + * uncorrectable errors will cause a system panic. 182 + * 183 + * MCA_CONFIG[MCAX] is bit 32 (0 in the high portion of the MSR.) 184 + */ 185 + high |= BIT(0); 186 + 187 + /* 188 + * SMCA sets the Deferred Error Interrupt type per bank. 189 + * 190 + * MCA_CONFIG[DeferredIntTypeSupported] is bit 5, and tells us 191 + * if the DeferredIntType bit field is available. 192 + * 193 + * MCA_CONFIG[DeferredIntType] is bits [38:37] ([6:5] in the 194 + * high portion of the MSR). OS should set this to 0x1 to enable 195 + * APIC based interrupt. First, check that no interrupt has been 196 + * set. 197 + */ 198 + if ((low & BIT(5)) && !((high >> 5) & 0x3)) 199 + high |= BIT(5); 200 + 201 + wrmsr(smca_config, low, high); 202 + } 203 204 /* Collect bank_info using CPU 0 for now. */ 205 if (cpu) 206 return; 207 208 + if (rdmsr_safe_on_cpu(cpu, MSR_AMD64_SMCA_MCx_IPID(bank), &low, &high)) { 209 pr_warn("Failed to read MCA_IPID for bank %d\n", bank); 210 return; 211 } ··· 191 smca_get_name(s_hwid->bank_type)); 192 193 smca_banks[bank].hwid = s_hwid; 194 + smca_banks[bank].id = low; 195 smca_banks[bank].sysfs_id = s_hwid->count++; 196 break; 197 } ··· 433 int offset, u32 misc_high) 434 { 435 unsigned int cpu = smp_processor_id(); 436 + u32 smca_low, smca_high; 437 struct threshold_block b; 438 int new; 439 ··· 455 if (!mce_flags.smca) { 456 new = (misc_high & MASK_LVTOFF_HI) >> 20; 457 goto set_offset; 458 } 459 460 /* Gather LVT offset for thresholding: */ ··· 530 531 for (bank = 0; bank < mca_cfg.banks; ++bank) { 532 if (mce_flags.smca) 533 + smca_configure(bank, cpu); 534 535 for (block = 0; block < NR_BLOCKS; ++block) { 536 address = get_block_address(cpu, address, low, high, bank, block); ··· 755 } 756 EXPORT_SYMBOL_GPL(umc_normaddr_to_sysaddr); 757 758 + static void __log_error(unsigned int bank, u64 status, u64 addr, u64 misc) 759 { 760 struct mce m; 761 762 mce_setup(&m); 763 764 m.status = status; 765 + m.misc = misc; 766 m.bank = bank; 767 m.tsc = rdtsc(); 768 769 if (m.status & MCI_STATUS_ADDRV) { 770 + m.addr = addr; 771 772 /* 773 * Extract [55:<lsb>] where lsb is the least significant ··· 806 } 807 808 mce_log(&m); 809 } 810 811 static inline void __smp_deferred_error_interrupt(void) ··· 832 exiting_ack_irq(); 833 } 834 835 + /* 836 + * Returns true if the logged error is deferred. False, otherwise. 837 + */ 838 + static inline bool 839 + _log_error_bank(unsigned int bank, u32 msr_stat, u32 msr_addr, u64 misc) 840 + { 841 + u64 status, addr = 0; 842 + 843 + rdmsrl(msr_stat, status); 844 + if (!(status & MCI_STATUS_VAL)) 845 + return false; 846 + 847 + if (status & MCI_STATUS_ADDRV) 848 + rdmsrl(msr_addr, addr); 849 + 850 + __log_error(bank, status, addr, misc); 851 + 852 + wrmsrl(msr_stat, 0); 853 + 854 + return status & MCI_STATUS_DEFERRED; 855 + } 856 + 857 + /* 858 + * We have three scenarios for checking for Deferred errors: 859 + * 860 + * 1) Non-SMCA systems check MCA_STATUS and log error if found. 861 + * 2) SMCA systems check MCA_STATUS. If error is found then log it and also 862 + * clear MCA_DESTAT. 863 + * 3) SMCA systems check MCA_DESTAT, if error was not found in MCA_STATUS, and 864 + * log it. 865 + */ 866 + static void log_error_deferred(unsigned int bank) 867 + { 868 + bool defrd; 869 + 870 + defrd = _log_error_bank(bank, msr_ops.status(bank), 871 + msr_ops.addr(bank), 0); 872 + 873 + if (!mce_flags.smca) 874 + return; 875 + 876 + /* Clear MCA_DESTAT if we logged the deferred error from MCA_STATUS. */ 877 + if (defrd) { 878 + wrmsrl(MSR_AMD64_SMCA_MCx_DESTAT(bank), 0); 879 + return; 880 + } 881 + 882 + /* 883 + * Only deferred errors are logged in MCA_DE{STAT,ADDR} so just check 884 + * for a valid error. 885 + */ 886 + _log_error_bank(bank, MSR_AMD64_SMCA_MCx_DESTAT(bank), 887 + MSR_AMD64_SMCA_MCx_DEADDR(bank), 0); 888 + } 889 + 890 /* APIC interrupt handler for deferred errors */ 891 static void amd_deferred_error_interrupt(void) 892 { 893 unsigned int bank; 894 895 + for (bank = 0; bank < mca_cfg.banks; ++bank) 896 + log_error_deferred(bank); 897 } 898 899 + static void log_error_thresholding(unsigned int bank, u64 misc) 900 { 901 + _log_error_bank(bank, msr_ops.status(bank), msr_ops.addr(bank), misc); 902 + } 903 + 904 + static void log_and_reset_block(struct threshold_block *block) 905 + { 906 struct thresh_restart tr; 907 + u32 low = 0, high = 0; 908 909 + if (!block) 910 + return; 911 912 + if (rdmsr_safe(block->address, &low, &high)) 913 + return; 914 915 + if (!(high & MASK_OVERFLOW_HI)) 916 + return; 917 918 + /* Log the MCE which caused the threshold event. */ 919 + log_error_thresholding(block->bank, ((u64)high << 32) | low); 920 921 /* Reset threshold block after logging error. */ 922 memset(&tr, 0, sizeof(tr)); 923 + tr.b = block; 924 threshold_restart_bank(&tr); 925 + } 926 + 927 + /* 928 + * Threshold interrupt handler will service THRESHOLD_APIC_VECTOR. The interrupt 929 + * goes off when error_count reaches threshold_limit. 930 + */ 931 + static void amd_threshold_interrupt(void) 932 + { 933 + struct threshold_block *first_block = NULL, *block = NULL, *tmp = NULL; 934 + unsigned int bank, cpu = smp_processor_id(); 935 + 936 + for (bank = 0; bank < mca_cfg.banks; ++bank) { 937 + if (!(per_cpu(bank_map, cpu) & (1 << bank))) 938 + continue; 939 + 940 + first_block = per_cpu(threshold_banks, cpu)[bank]->blocks; 941 + if (!first_block) 942 + continue; 943 + 944 + /* 945 + * The first block is also the head of the list. Check it first 946 + * before iterating over the rest. 947 + */ 948 + log_and_reset_block(first_block); 949 + list_for_each_entry_safe(block, tmp, &first_block->miscj, miscj) 950 + log_and_reset_block(block); 951 + } 952 } 953 954 /* ··· 1202 goto out; 1203 1204 per_cpu(threshold_banks, cpu)[bank] = b; 1205 + refcount_inc(&b->cpus); 1206 1207 err = __threshold_add_blocks(b); 1208 ··· 1225 per_cpu(threshold_banks, cpu)[bank] = b; 1226 1227 if (is_shared_bank(bank)) { 1228 + refcount_set(&b->cpus, 1); 1229 1230 /* nb is already initialized, see above */ 1231 if (nb) { ··· 1289 goto free_out; 1290 1291 if (is_shared_bank(bank)) { 1292 + if (!refcount_dec_and_test(&b->cpus)) { 1293 __threshold_remove_blocks(b); 1294 per_cpu(threshold_banks, cpu)[bank] = NULL; 1295 return;
-11
arch/x86/ras/Kconfig
··· 1 - config MCE_AMD_INJ 2 - tristate "Simple MCE injection interface for AMD processors" 3 - depends on RAS && X86_MCE && DEBUG_FS && AMD_NB 4 - default n 5 - help 6 - This is a simple debugfs interface to inject MCEs and test different 7 - aspects of the MCE handling code. 8 - 9 - WARNING: Do not even assume this interface is staying stable! 10 - 11 config RAS_CEC 12 bool "Correctable Errors Collector" 13 depends on X86_MCE && MEMORY_FAILURE && DEBUG_FS ··· 10 11 Bear in mind that this is absolutely useless if your platform doesn't 12 have ECC DIMMs and doesn't have DRAM ECC checking enabled in the BIOS. 13 -
··· 1 config RAS_CEC 2 bool "Correctable Errors Collector" 3 depends on X86_MCE && MEMORY_FAILURE && DEBUG_FS ··· 20 21 Bear in mind that this is absolutely useless if your platform doesn't 22 have ECC DIMMs and doesn't have DRAM ECC checking enabled in the BIOS.
-2
arch/x86/ras/Makefile
··· 1 - obj-$(CONFIG_MCE_AMD_INJ) += mce_amd_inj.o 2 -
···
-492
arch/x86/ras/mce_amd_inj.c
··· 1 - /* 2 - * A simple MCE injection facility for testing different aspects of the RAS 3 - * code. This driver should be built as module so that it can be loaded 4 - * on production kernels for testing purposes. 5 - * 6 - * This file may be distributed under the terms of the GNU General Public 7 - * License version 2. 8 - * 9 - * Copyright (c) 2010-15: Borislav Petkov <bp@alien8.de> 10 - * Advanced Micro Devices Inc. 11 - */ 12 - 13 - #include <linux/kobject.h> 14 - #include <linux/debugfs.h> 15 - #include <linux/device.h> 16 - #include <linux/module.h> 17 - #include <linux/cpu.h> 18 - #include <linux/string.h> 19 - #include <linux/uaccess.h> 20 - #include <linux/pci.h> 21 - 22 - #include <asm/mce.h> 23 - #include <asm/smp.h> 24 - #include <asm/amd_nb.h> 25 - #include <asm/irq_vectors.h> 26 - 27 - #include "../kernel/cpu/mcheck/mce-internal.h" 28 - 29 - /* 30 - * Collect all the MCi_XXX settings 31 - */ 32 - static struct mce i_mce; 33 - static struct dentry *dfs_inj; 34 - 35 - static u8 n_banks; 36 - 37 - #define MAX_FLAG_OPT_SIZE 3 38 - #define NBCFG 0x44 39 - 40 - enum injection_type { 41 - SW_INJ = 0, /* SW injection, simply decode the error */ 42 - HW_INJ, /* Trigger a #MC */ 43 - DFR_INT_INJ, /* Trigger Deferred error interrupt */ 44 - THR_INT_INJ, /* Trigger threshold interrupt */ 45 - N_INJ_TYPES, 46 - }; 47 - 48 - static const char * const flags_options[] = { 49 - [SW_INJ] = "sw", 50 - [HW_INJ] = "hw", 51 - [DFR_INT_INJ] = "df", 52 - [THR_INT_INJ] = "th", 53 - NULL 54 - }; 55 - 56 - /* Set default injection to SW_INJ */ 57 - static enum injection_type inj_type = SW_INJ; 58 - 59 - #define MCE_INJECT_SET(reg) \ 60 - static int inj_##reg##_set(void *data, u64 val) \ 61 - { \ 62 - struct mce *m = (struct mce *)data; \ 63 - \ 64 - m->reg = val; \ 65 - return 0; \ 66 - } 67 - 68 - MCE_INJECT_SET(status); 69 - MCE_INJECT_SET(misc); 70 - MCE_INJECT_SET(addr); 71 - MCE_INJECT_SET(synd); 72 - 73 - #define MCE_INJECT_GET(reg) \ 74 - static int inj_##reg##_get(void *data, u64 *val) \ 75 - { \ 76 - struct mce *m = (struct mce *)data; \ 77 - \ 78 - *val = m->reg; \ 79 - return 0; \ 80 - } 81 - 82 - MCE_INJECT_GET(status); 83 - MCE_INJECT_GET(misc); 84 - MCE_INJECT_GET(addr); 85 - MCE_INJECT_GET(synd); 86 - 87 - DEFINE_SIMPLE_ATTRIBUTE(status_fops, inj_status_get, inj_status_set, "%llx\n"); 88 - DEFINE_SIMPLE_ATTRIBUTE(misc_fops, inj_misc_get, inj_misc_set, "%llx\n"); 89 - DEFINE_SIMPLE_ATTRIBUTE(addr_fops, inj_addr_get, inj_addr_set, "%llx\n"); 90 - DEFINE_SIMPLE_ATTRIBUTE(synd_fops, inj_synd_get, inj_synd_set, "%llx\n"); 91 - 92 - /* 93 - * Caller needs to be make sure this cpu doesn't disappear 94 - * from under us, i.e.: get_cpu/put_cpu. 95 - */ 96 - static int toggle_hw_mce_inject(unsigned int cpu, bool enable) 97 - { 98 - u32 l, h; 99 - int err; 100 - 101 - err = rdmsr_on_cpu(cpu, MSR_K7_HWCR, &l, &h); 102 - if (err) { 103 - pr_err("%s: error reading HWCR\n", __func__); 104 - return err; 105 - } 106 - 107 - enable ? (l |= BIT(18)) : (l &= ~BIT(18)); 108 - 109 - err = wrmsr_on_cpu(cpu, MSR_K7_HWCR, l, h); 110 - if (err) 111 - pr_err("%s: error writing HWCR\n", __func__); 112 - 113 - return err; 114 - } 115 - 116 - static int __set_inj(const char *buf) 117 - { 118 - int i; 119 - 120 - for (i = 0; i < N_INJ_TYPES; i++) { 121 - if (!strncmp(flags_options[i], buf, strlen(flags_options[i]))) { 122 - inj_type = i; 123 - return 0; 124 - } 125 - } 126 - return -EINVAL; 127 - } 128 - 129 - static ssize_t flags_read(struct file *filp, char __user *ubuf, 130 - size_t cnt, loff_t *ppos) 131 - { 132 - char buf[MAX_FLAG_OPT_SIZE]; 133 - int n; 134 - 135 - n = sprintf(buf, "%s\n", flags_options[inj_type]); 136 - 137 - return simple_read_from_buffer(ubuf, cnt, ppos, buf, n); 138 - } 139 - 140 - static ssize_t flags_write(struct file *filp, const char __user *ubuf, 141 - size_t cnt, loff_t *ppos) 142 - { 143 - char buf[MAX_FLAG_OPT_SIZE], *__buf; 144 - int err; 145 - 146 - if (cnt > MAX_FLAG_OPT_SIZE) 147 - return -EINVAL; 148 - 149 - if (copy_from_user(&buf, ubuf, cnt)) 150 - return -EFAULT; 151 - 152 - buf[cnt - 1] = 0; 153 - 154 - /* strip whitespace */ 155 - __buf = strstrip(buf); 156 - 157 - err = __set_inj(__buf); 158 - if (err) { 159 - pr_err("%s: Invalid flags value: %s\n", __func__, __buf); 160 - return err; 161 - } 162 - 163 - *ppos += cnt; 164 - 165 - return cnt; 166 - } 167 - 168 - static const struct file_operations flags_fops = { 169 - .read = flags_read, 170 - .write = flags_write, 171 - .llseek = generic_file_llseek, 172 - }; 173 - 174 - /* 175 - * On which CPU to inject? 176 - */ 177 - MCE_INJECT_GET(extcpu); 178 - 179 - static int inj_extcpu_set(void *data, u64 val) 180 - { 181 - struct mce *m = (struct mce *)data; 182 - 183 - if (val >= nr_cpu_ids || !cpu_online(val)) { 184 - pr_err("%s: Invalid CPU: %llu\n", __func__, val); 185 - return -EINVAL; 186 - } 187 - m->extcpu = val; 188 - return 0; 189 - } 190 - 191 - DEFINE_SIMPLE_ATTRIBUTE(extcpu_fops, inj_extcpu_get, inj_extcpu_set, "%llu\n"); 192 - 193 - static void trigger_mce(void *info) 194 - { 195 - asm volatile("int $18"); 196 - } 197 - 198 - static void trigger_dfr_int(void *info) 199 - { 200 - asm volatile("int %0" :: "i" (DEFERRED_ERROR_VECTOR)); 201 - } 202 - 203 - static void trigger_thr_int(void *info) 204 - { 205 - asm volatile("int %0" :: "i" (THRESHOLD_APIC_VECTOR)); 206 - } 207 - 208 - static u32 get_nbc_for_node(int node_id) 209 - { 210 - struct cpuinfo_x86 *c = &boot_cpu_data; 211 - u32 cores_per_node; 212 - 213 - cores_per_node = (c->x86_max_cores * smp_num_siblings) / amd_get_nodes_per_socket(); 214 - 215 - return cores_per_node * node_id; 216 - } 217 - 218 - static void toggle_nb_mca_mst_cpu(u16 nid) 219 - { 220 - struct pci_dev *F3 = node_to_amd_nb(nid)->misc; 221 - u32 val; 222 - int err; 223 - 224 - if (!F3) 225 - return; 226 - 227 - err = pci_read_config_dword(F3, NBCFG, &val); 228 - if (err) { 229 - pr_err("%s: Error reading F%dx%03x.\n", 230 - __func__, PCI_FUNC(F3->devfn), NBCFG); 231 - return; 232 - } 233 - 234 - if (val & BIT(27)) 235 - return; 236 - 237 - pr_err("%s: Set D18F3x44[NbMcaToMstCpuEn] which BIOS hasn't done.\n", 238 - __func__); 239 - 240 - val |= BIT(27); 241 - err = pci_write_config_dword(F3, NBCFG, val); 242 - if (err) 243 - pr_err("%s: Error writing F%dx%03x.\n", 244 - __func__, PCI_FUNC(F3->devfn), NBCFG); 245 - } 246 - 247 - static void prepare_msrs(void *info) 248 - { 249 - struct mce m = *(struct mce *)info; 250 - u8 b = m.bank; 251 - 252 - wrmsrl(MSR_IA32_MCG_STATUS, m.mcgstatus); 253 - 254 - if (boot_cpu_has(X86_FEATURE_SMCA)) { 255 - if (m.inject_flags == DFR_INT_INJ) { 256 - wrmsrl(MSR_AMD64_SMCA_MCx_DESTAT(b), m.status); 257 - wrmsrl(MSR_AMD64_SMCA_MCx_DEADDR(b), m.addr); 258 - } else { 259 - wrmsrl(MSR_AMD64_SMCA_MCx_STATUS(b), m.status); 260 - wrmsrl(MSR_AMD64_SMCA_MCx_ADDR(b), m.addr); 261 - } 262 - 263 - wrmsrl(MSR_AMD64_SMCA_MCx_MISC(b), m.misc); 264 - wrmsrl(MSR_AMD64_SMCA_MCx_SYND(b), m.synd); 265 - } else { 266 - wrmsrl(MSR_IA32_MCx_STATUS(b), m.status); 267 - wrmsrl(MSR_IA32_MCx_ADDR(b), m.addr); 268 - wrmsrl(MSR_IA32_MCx_MISC(b), m.misc); 269 - } 270 - } 271 - 272 - static void do_inject(void) 273 - { 274 - u64 mcg_status = 0; 275 - unsigned int cpu = i_mce.extcpu; 276 - u8 b = i_mce.bank; 277 - 278 - rdtscll(i_mce.tsc); 279 - 280 - if (i_mce.misc) 281 - i_mce.status |= MCI_STATUS_MISCV; 282 - 283 - if (i_mce.synd) 284 - i_mce.status |= MCI_STATUS_SYNDV; 285 - 286 - if (inj_type == SW_INJ) { 287 - mce_inject_log(&i_mce); 288 - return; 289 - } 290 - 291 - /* prep MCE global settings for the injection */ 292 - mcg_status = MCG_STATUS_MCIP | MCG_STATUS_EIPV; 293 - 294 - if (!(i_mce.status & MCI_STATUS_PCC)) 295 - mcg_status |= MCG_STATUS_RIPV; 296 - 297 - /* 298 - * Ensure necessary status bits for deferred errors: 299 - * - MCx_STATUS[Deferred]: make sure it is a deferred error 300 - * - MCx_STATUS[UC] cleared: deferred errors are _not_ UC 301 - */ 302 - if (inj_type == DFR_INT_INJ) { 303 - i_mce.status |= MCI_STATUS_DEFERRED; 304 - i_mce.status |= (i_mce.status & ~MCI_STATUS_UC); 305 - } 306 - 307 - /* 308 - * For multi node CPUs, logging and reporting of bank 4 errors happens 309 - * only on the node base core. Refer to D18F3x44[NbMcaToMstCpuEn] for 310 - * Fam10h and later BKDGs. 311 - */ 312 - if (static_cpu_has(X86_FEATURE_AMD_DCM) && 313 - b == 4 && 314 - boot_cpu_data.x86 < 0x17) { 315 - toggle_nb_mca_mst_cpu(amd_get_nb_id(cpu)); 316 - cpu = get_nbc_for_node(amd_get_nb_id(cpu)); 317 - } 318 - 319 - get_online_cpus(); 320 - if (!cpu_online(cpu)) 321 - goto err; 322 - 323 - toggle_hw_mce_inject(cpu, true); 324 - 325 - i_mce.mcgstatus = mcg_status; 326 - i_mce.inject_flags = inj_type; 327 - smp_call_function_single(cpu, prepare_msrs, &i_mce, 0); 328 - 329 - toggle_hw_mce_inject(cpu, false); 330 - 331 - switch (inj_type) { 332 - case DFR_INT_INJ: 333 - smp_call_function_single(cpu, trigger_dfr_int, NULL, 0); 334 - break; 335 - case THR_INT_INJ: 336 - smp_call_function_single(cpu, trigger_thr_int, NULL, 0); 337 - break; 338 - default: 339 - smp_call_function_single(cpu, trigger_mce, NULL, 0); 340 - } 341 - 342 - err: 343 - put_online_cpus(); 344 - 345 - } 346 - 347 - /* 348 - * This denotes into which bank we're injecting and triggers 349 - * the injection, at the same time. 350 - */ 351 - static int inj_bank_set(void *data, u64 val) 352 - { 353 - struct mce *m = (struct mce *)data; 354 - 355 - if (val >= n_banks) { 356 - pr_err("Non-existent MCE bank: %llu\n", val); 357 - return -EINVAL; 358 - } 359 - 360 - m->bank = val; 361 - do_inject(); 362 - 363 - return 0; 364 - } 365 - 366 - MCE_INJECT_GET(bank); 367 - 368 - DEFINE_SIMPLE_ATTRIBUTE(bank_fops, inj_bank_get, inj_bank_set, "%llu\n"); 369 - 370 - static const char readme_msg[] = 371 - "Description of the files and their usages:\n" 372 - "\n" 373 - "Note1: i refers to the bank number below.\n" 374 - "Note2: See respective BKDGs for the exact bit definitions of the files below\n" 375 - "as they mirror the hardware registers.\n" 376 - "\n" 377 - "status:\t Set MCi_STATUS: the bits in that MSR control the error type and\n" 378 - "\t attributes of the error which caused the MCE.\n" 379 - "\n" 380 - "misc:\t Set MCi_MISC: provide auxiliary info about the error. It is mostly\n" 381 - "\t used for error thresholding purposes and its validity is indicated by\n" 382 - "\t MCi_STATUS[MiscV].\n" 383 - "\n" 384 - "synd:\t Set MCi_SYND: provide syndrome info about the error. Only valid on\n" 385 - "\t Scalable MCA systems, and its validity is indicated by MCi_STATUS[SyndV].\n" 386 - "\n" 387 - "addr:\t Error address value to be written to MCi_ADDR. Log address information\n" 388 - "\t associated with the error.\n" 389 - "\n" 390 - "cpu:\t The CPU to inject the error on.\n" 391 - "\n" 392 - "bank:\t Specify the bank you want to inject the error into: the number of\n" 393 - "\t banks in a processor varies and is family/model-specific, therefore, the\n" 394 - "\t supplied value is sanity-checked. Setting the bank value also triggers the\n" 395 - "\t injection.\n" 396 - "\n" 397 - "flags:\t Injection type to be performed. Writing to this file will trigger a\n" 398 - "\t real machine check, an APIC interrupt or invoke the error decoder routines\n" 399 - "\t for AMD processors.\n" 400 - "\n" 401 - "\t Allowed error injection types:\n" 402 - "\t - \"sw\": Software error injection. Decode error to a human-readable \n" 403 - "\t format only. Safe to use.\n" 404 - "\t - \"hw\": Hardware error injection. Causes the #MC exception handler to \n" 405 - "\t handle the error. Be warned: might cause system panic if MCi_STATUS[PCC] \n" 406 - "\t is set. Therefore, consider setting (debugfs_mountpoint)/mce/fake_panic \n" 407 - "\t before injecting.\n" 408 - "\t - \"df\": Trigger APIC interrupt for Deferred error. Causes deferred \n" 409 - "\t error APIC interrupt handler to handle the error if the feature is \n" 410 - "\t is present in hardware. \n" 411 - "\t - \"th\": Trigger APIC interrupt for Threshold errors. Causes threshold \n" 412 - "\t APIC interrupt handler to handle the error. \n" 413 - "\n"; 414 - 415 - static ssize_t 416 - inj_readme_read(struct file *filp, char __user *ubuf, 417 - size_t cnt, loff_t *ppos) 418 - { 419 - return simple_read_from_buffer(ubuf, cnt, ppos, 420 - readme_msg, strlen(readme_msg)); 421 - } 422 - 423 - static const struct file_operations readme_fops = { 424 - .read = inj_readme_read, 425 - }; 426 - 427 - static struct dfs_node { 428 - char *name; 429 - struct dentry *d; 430 - const struct file_operations *fops; 431 - umode_t perm; 432 - } dfs_fls[] = { 433 - { .name = "status", .fops = &status_fops, .perm = S_IRUSR | S_IWUSR }, 434 - { .name = "misc", .fops = &misc_fops, .perm = S_IRUSR | S_IWUSR }, 435 - { .name = "addr", .fops = &addr_fops, .perm = S_IRUSR | S_IWUSR }, 436 - { .name = "synd", .fops = &synd_fops, .perm = S_IRUSR | S_IWUSR }, 437 - { .name = "bank", .fops = &bank_fops, .perm = S_IRUSR | S_IWUSR }, 438 - { .name = "flags", .fops = &flags_fops, .perm = S_IRUSR | S_IWUSR }, 439 - { .name = "cpu", .fops = &extcpu_fops, .perm = S_IRUSR | S_IWUSR }, 440 - { .name = "README", .fops = &readme_fops, .perm = S_IRUSR | S_IRGRP | S_IROTH }, 441 - }; 442 - 443 - static int __init init_mce_inject(void) 444 - { 445 - unsigned int i; 446 - u64 cap; 447 - 448 - rdmsrl(MSR_IA32_MCG_CAP, cap); 449 - n_banks = cap & MCG_BANKCNT_MASK; 450 - 451 - dfs_inj = debugfs_create_dir("mce-inject", NULL); 452 - if (!dfs_inj) 453 - return -EINVAL; 454 - 455 - for (i = 0; i < ARRAY_SIZE(dfs_fls); i++) { 456 - dfs_fls[i].d = debugfs_create_file(dfs_fls[i].name, 457 - dfs_fls[i].perm, 458 - dfs_inj, 459 - &i_mce, 460 - dfs_fls[i].fops); 461 - 462 - if (!dfs_fls[i].d) 463 - goto err_dfs_add; 464 - } 465 - 466 - return 0; 467 - 468 - err_dfs_add: 469 - while (i-- > 0) 470 - debugfs_remove(dfs_fls[i].d); 471 - 472 - debugfs_remove(dfs_inj); 473 - dfs_inj = NULL; 474 - 475 - return -ENODEV; 476 - } 477 - 478 - static void __exit exit_mce_inject(void) 479 - { 480 - 481 - debugfs_remove_recursive(dfs_inj); 482 - dfs_inj = NULL; 483 - 484 - memset(&dfs_fls, 0, sizeof(dfs_fls)); 485 - } 486 - module_init(init_mce_inject); 487 - module_exit(exit_mce_inject); 488 - 489 - MODULE_LICENSE("GPL"); 490 - MODULE_AUTHOR("Borislav Petkov <bp@alien8.de>"); 491 - MODULE_AUTHOR("AMD Inc."); 492 - MODULE_DESCRIPTION("MCE injection facility for RAS testing");
···
+25 -14
drivers/acpi/apei/ghes.c
··· 89 module_param_named(disable, ghes_disable, bool, 0); 90 91 /* 92 - * All error sources notified with SCI shares one notifier function, 93 - * so they need to be linked and checked one by one. This is applied 94 - * to NMI too. 95 * 96 * RCU is used for these lists, so ghes_list_mutex is only used for 97 * list changing, not for traversing. 98 */ 99 - static LIST_HEAD(ghes_sci); 100 static DEFINE_MUTEX(ghes_list_mutex); 101 102 /* ··· 702 return IRQ_HANDLED; 703 } 704 705 - static int ghes_notify_sci(struct notifier_block *this, 706 - unsigned long event, void *data) 707 { 708 struct ghes *ghes; 709 int ret = NOTIFY_DONE; 710 711 rcu_read_lock(); 712 - list_for_each_entry_rcu(ghes, &ghes_sci, list) { 713 if (!ghes_proc(ghes)) 714 ret = NOTIFY_OK; 715 } ··· 718 return ret; 719 } 720 721 - static struct notifier_block ghes_notifier_sci = { 722 - .notifier_call = ghes_notify_sci, 723 }; 724 725 #ifdef CONFIG_HAVE_ACPI_APEI_NMI ··· 966 case ACPI_HEST_NOTIFY_POLLED: 967 case ACPI_HEST_NOTIFY_EXTERNAL: 968 case ACPI_HEST_NOTIFY_SCI: 969 break; 970 case ACPI_HEST_NOTIFY_NMI: 971 if (!IS_ENABLED(CONFIG_HAVE_ACPI_APEI_NMI)) { 972 pr_warn(GHES_PFX "Generic hardware error source: %d notified via NMI interrupt is not supported!\n", ··· 1027 goto err_edac_unreg; 1028 } 1029 break; 1030 case ACPI_HEST_NOTIFY_SCI: 1031 mutex_lock(&ghes_list_mutex); 1032 - if (list_empty(&ghes_sci)) 1033 - register_acpi_hed_notifier(&ghes_notifier_sci); 1034 - list_add_rcu(&ghes->list, &ghes_sci); 1035 mutex_unlock(&ghes_list_mutex); 1036 break; 1037 case ACPI_HEST_NOTIFY_NMI: 1038 ghes_nmi_add(ghes); 1039 break; ··· 1073 case ACPI_HEST_NOTIFY_EXTERNAL: 1074 free_irq(ghes->irq, ghes); 1075 break; 1076 case ACPI_HEST_NOTIFY_SCI: 1077 mutex_lock(&ghes_list_mutex); 1078 list_del_rcu(&ghes->list); 1079 - if (list_empty(&ghes_sci)) 1080 - unregister_acpi_hed_notifier(&ghes_notifier_sci); 1081 mutex_unlock(&ghes_list_mutex); 1082 synchronize_rcu(); 1083 break; 1084 case ACPI_HEST_NOTIFY_NMI: 1085 ghes_nmi_remove(ghes); 1086 break;
··· 89 module_param_named(disable, ghes_disable, bool, 0); 90 91 /* 92 + * All error sources notified with HED (Hardware Error Device) share a 93 + * single notifier callback, so they need to be linked and checked one 94 + * by one. This holds true for NMI too. 95 * 96 * RCU is used for these lists, so ghes_list_mutex is only used for 97 * list changing, not for traversing. 98 */ 99 + static LIST_HEAD(ghes_hed); 100 static DEFINE_MUTEX(ghes_list_mutex); 101 102 /* ··· 702 return IRQ_HANDLED; 703 } 704 705 + static int ghes_notify_hed(struct notifier_block *this, unsigned long event, 706 + void *data) 707 { 708 struct ghes *ghes; 709 int ret = NOTIFY_DONE; 710 711 rcu_read_lock(); 712 + list_for_each_entry_rcu(ghes, &ghes_hed, list) { 713 if (!ghes_proc(ghes)) 714 ret = NOTIFY_OK; 715 } ··· 718 return ret; 719 } 720 721 + static struct notifier_block ghes_notifier_hed = { 722 + .notifier_call = ghes_notify_hed, 723 }; 724 725 #ifdef CONFIG_HAVE_ACPI_APEI_NMI ··· 966 case ACPI_HEST_NOTIFY_POLLED: 967 case ACPI_HEST_NOTIFY_EXTERNAL: 968 case ACPI_HEST_NOTIFY_SCI: 969 + case ACPI_HEST_NOTIFY_GSIV: 970 + case ACPI_HEST_NOTIFY_GPIO: 971 break; 972 + 973 case ACPI_HEST_NOTIFY_NMI: 974 if (!IS_ENABLED(CONFIG_HAVE_ACPI_APEI_NMI)) { 975 pr_warn(GHES_PFX "Generic hardware error source: %d notified via NMI interrupt is not supported!\n", ··· 1024 goto err_edac_unreg; 1025 } 1026 break; 1027 + 1028 case ACPI_HEST_NOTIFY_SCI: 1029 + case ACPI_HEST_NOTIFY_GSIV: 1030 + case ACPI_HEST_NOTIFY_GPIO: 1031 mutex_lock(&ghes_list_mutex); 1032 + if (list_empty(&ghes_hed)) 1033 + register_acpi_hed_notifier(&ghes_notifier_hed); 1034 + list_add_rcu(&ghes->list, &ghes_hed); 1035 mutex_unlock(&ghes_list_mutex); 1036 break; 1037 + 1038 case ACPI_HEST_NOTIFY_NMI: 1039 ghes_nmi_add(ghes); 1040 break; ··· 1066 case ACPI_HEST_NOTIFY_EXTERNAL: 1067 free_irq(ghes->irq, ghes); 1068 break; 1069 + 1070 case ACPI_HEST_NOTIFY_SCI: 1071 + case ACPI_HEST_NOTIFY_GSIV: 1072 + case ACPI_HEST_NOTIFY_GPIO: 1073 mutex_lock(&ghes_list_mutex); 1074 list_del_rcu(&ghes->list); 1075 + if (list_empty(&ghes_hed)) 1076 + unregister_acpi_hed_notifier(&ghes_notifier_hed); 1077 mutex_unlock(&ghes_list_mutex); 1078 synchronize_rcu(); 1079 break; 1080 + 1081 case ACPI_HEST_NOTIFY_NMI: 1082 ghes_nmi_remove(ghes); 1083 break;
+1 -1
drivers/ras/cec.c
··· 481 482 count = debugfs_create_file("count_threshold", S_IRUSR | S_IWUSR, d, 483 &count_threshold, &count_threshold_ops); 484 - if (!decay) { 485 pr_warn("Error creating count_threshold debugfs node!\n"); 486 goto err; 487 }
··· 481 482 count = debugfs_create_file("count_threshold", S_IRUSR | S_IWUSR, d, 483 &count_threshold, &count_threshold_ops); 484 + if (!count) { 485 pr_warn("Error creating count_threshold debugfs node!\n"); 486 goto err; 487 }
+1 -1
drivers/ras/ras.c
··· 29 EXPORT_TRACEPOINT_SYMBOL_GPL(mc_event); 30 31 32 - int __init parse_ras_param(char *str) 33 { 34 #ifdef CONFIG_RAS_CEC 35 parse_cec_param(str);
··· 29 EXPORT_TRACEPOINT_SYMBOL_GPL(mc_event); 30 31 32 + static int __init parse_ras_param(char *str) 33 { 34 #ifdef CONFIG_RAS_CEC 35 parse_cec_param(str);
+2
drivers/xen/mcelog.c
··· 408 if (ret) 409 goto deregister; 410 411 return 0; 412 413 deregister:
··· 408 if (ret) 409 goto deregister; 410 411 + pr_info("/dev/mcelog registered by Xen\n"); 412 + 413 return 0; 414 415 deregister: