diff options
author | Borislav Petkov <bp@suse.de> | 2017-06-13 18:28:31 +0200 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2017-06-14 07:32:07 +0200 |
commit | fbe9ff9eafb66b78b79c135ebc24fd2ca5498217 (patch) | |
tree | f9b44c922da0702c799282408203a72ab34ebcfa /arch/x86/kernel/cpu/mcheck/mce-inject.c | |
parent | bc8e80d56c1ecb35e65df392d7601d1427d14efe (diff) | |
download | lwn-fbe9ff9eafb66b78b79c135ebc24fd2ca5498217.tar.gz lwn-fbe9ff9eafb66b78b79c135ebc24fd2ca5498217.zip |
x86/mce: Get rid of register_mce_write_callback()
Make the mcelog call a notifier which lands in the injector module and
does the injection. This allows for mce-inject to be a normal kernel
module now.
Tested-by: Yazen Ghannam <yazen.ghannam@amd.com>
Signed-off-by: Borislav Petkov <bp@suse.de>
Acked-by: Yazen Ghannam <yazen.ghannam@amd.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Tony Luck <tony.luck@intel.com>
Link: http://lkml.kernel.org/r/20170613162835.30750-5-bp@alien8.de
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'arch/x86/kernel/cpu/mcheck/mce-inject.c')
-rw-r--r-- | arch/x86/kernel/cpu/mcheck/mce-inject.c | 66 |
1 files changed, 19 insertions, 47 deletions
diff --git a/arch/x86/kernel/cpu/mcheck/mce-inject.c b/arch/x86/kernel/cpu/mcheck/mce-inject.c index 7170186938e5..c21c1a73712a 100644 --- a/arch/x86/kernel/cpu/mcheck/mce-inject.c +++ b/arch/x86/kernel/cpu/mcheck/mce-inject.c @@ -283,42 +283,24 @@ static void __maybe_unused raise_mce(struct mce *m) } } -#ifdef CONFIG_X86_MCELOG_LEGACY -/* Error injection interface */ -static ssize_t mce_write(struct file *filp, const char __user *ubuf, - size_t usize, loff_t *off) +static int mce_inject_raise(struct notifier_block *nb, unsigned long val, + void *data) { - struct mce m; - - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - /* - * There are some cases where real MSR reads could slip - * through. - */ - if (!boot_cpu_has(X86_FEATURE_MCE) || !boot_cpu_has(X86_FEATURE_MCA)) - return -EIO; - - if ((unsigned long)usize > sizeof(struct mce)) - usize = sizeof(struct mce); - if (copy_from_user(&m, ubuf, usize)) - return -EFAULT; - - if (m.extcpu >= num_possible_cpus() || !cpu_online(m.extcpu)) - return -EINVAL; + struct mce *m = (struct mce *)data; - /* - * Need to give user space some time to set everything up, - * so do it a jiffie or two later everywhere. - */ - schedule_timeout(2); + if (!m) + return NOTIFY_DONE; mutex_lock(&mce_inject_mutex); - raise_mce(&m); + raise_mce(m); mutex_unlock(&mce_inject_mutex); - return usize; + + return NOTIFY_DONE; } -#endif /* CONFIG_X86_MCELOG_LEGACY */ + +static struct notifier_block inject_nb = { + .notifier_call = mce_inject_raise, +}; /* * Caller needs to be make sure this cpu doesn't disappear @@ -719,44 +701,34 @@ static int __init inject_init(void) if (!alloc_cpumask_var(&mce_inject_cpumask, GFP_KERNEL)) return -ENOMEM; -#ifdef CONFIG_X86_MCELOG_LEGACY - register_mce_write_callback(mce_write); -#endif - - register_nmi_handler(NMI_LOCAL, mce_raise_notify, 0, "mce_notify"); - err = debugfs_init(); if (err) { free_cpumask_var(mce_inject_cpumask); return err; } + register_nmi_handler(NMI_LOCAL, mce_raise_notify, 0, "mce_notify"); + mce_register_injector_chain(&inject_nb); + pr_info("Machine check injector initialized\n"); return 0; } -module_init(inject_init); - -/* - * Cannot tolerate unloading currently because we cannot - * guarantee all openers of mce_chrdev will get a reference to us. - */ -#ifndef CONFIG_X86_MCELOG_LEGACY static void __exit inject_exit(void) { + mce_unregister_injector_chain(&inject_nb); + unregister_nmi_handler(NMI_LOCAL, "mce_notify"); + debugfs_remove_recursive(dfs_inj); dfs_inj = NULL; memset(&dfs_fls, 0, sizeof(dfs_fls)); - unregister_nmi_handler(NMI_LOCAL, "mce_notify"); - free_cpumask_var(mce_inject_cpumask); } +module_init(inject_init); module_exit(inject_exit); -#endif - MODULE_LICENSE("GPL"); |