xref: /linux/mm/hwpoison-inject.c (revision 847ce401df392b0704369fd3f75df614ac1414b4)
1cae681fcSAndi Kleen /* Inject a hwpoison memory failure on a arbitary pfn */
2cae681fcSAndi Kleen #include <linux/module.h>
3cae681fcSAndi Kleen #include <linux/debugfs.h>
4cae681fcSAndi Kleen #include <linux/kernel.h>
5cae681fcSAndi Kleen #include <linux/mm.h>
6cae681fcSAndi Kleen 
7*847ce401SWu Fengguang static struct dentry *hwpoison_dir;
8cae681fcSAndi Kleen 
9cae681fcSAndi Kleen static int hwpoison_inject(void *data, u64 val)
10cae681fcSAndi Kleen {
11cae681fcSAndi Kleen 	if (!capable(CAP_SYS_ADMIN))
12cae681fcSAndi Kleen 		return -EPERM;
13cae681fcSAndi Kleen 	printk(KERN_INFO "Injecting memory failure at pfn %Lx\n", val);
14cae681fcSAndi Kleen 	return __memory_failure(val, 18, 0);
15cae681fcSAndi Kleen }
16cae681fcSAndi Kleen 
17*847ce401SWu Fengguang static int hwpoison_unpoison(void *data, u64 val)
18*847ce401SWu Fengguang {
19*847ce401SWu Fengguang 	if (!capable(CAP_SYS_ADMIN))
20*847ce401SWu Fengguang 		return -EPERM;
21*847ce401SWu Fengguang 
22*847ce401SWu Fengguang 	return unpoison_memory(val);
23*847ce401SWu Fengguang }
24*847ce401SWu Fengguang 
25cae681fcSAndi Kleen DEFINE_SIMPLE_ATTRIBUTE(hwpoison_fops, NULL, hwpoison_inject, "%lli\n");
26*847ce401SWu Fengguang DEFINE_SIMPLE_ATTRIBUTE(unpoison_fops, NULL, hwpoison_unpoison, "%lli\n");
27cae681fcSAndi Kleen 
28cae681fcSAndi Kleen static void pfn_inject_exit(void)
29cae681fcSAndi Kleen {
30cae681fcSAndi Kleen 	if (hwpoison_dir)
31cae681fcSAndi Kleen 		debugfs_remove_recursive(hwpoison_dir);
32cae681fcSAndi Kleen }
33cae681fcSAndi Kleen 
34cae681fcSAndi Kleen static int pfn_inject_init(void)
35cae681fcSAndi Kleen {
36*847ce401SWu Fengguang 	struct dentry *dentry;
37*847ce401SWu Fengguang 
38cae681fcSAndi Kleen 	hwpoison_dir = debugfs_create_dir("hwpoison", NULL);
39cae681fcSAndi Kleen 	if (hwpoison_dir == NULL)
40cae681fcSAndi Kleen 		return -ENOMEM;
41*847ce401SWu Fengguang 
42*847ce401SWu Fengguang 	/*
43*847ce401SWu Fengguang 	 * Note that the below poison/unpoison interfaces do not involve
44*847ce401SWu Fengguang 	 * hardware status change, hence do not require hardware support.
45*847ce401SWu Fengguang 	 * They are mainly for testing hwpoison in software level.
46*847ce401SWu Fengguang 	 */
47*847ce401SWu Fengguang 	dentry = debugfs_create_file("corrupt-pfn", 0600, hwpoison_dir,
48cae681fcSAndi Kleen 					  NULL, &hwpoison_fops);
49*847ce401SWu Fengguang 	if (!dentry)
50*847ce401SWu Fengguang 		goto fail;
51*847ce401SWu Fengguang 
52*847ce401SWu Fengguang 	dentry = debugfs_create_file("unpoison-pfn", 0600, hwpoison_dir,
53*847ce401SWu Fengguang 				     NULL, &unpoison_fops);
54*847ce401SWu Fengguang 	if (!dentry)
55*847ce401SWu Fengguang 		goto fail;
56*847ce401SWu Fengguang 
57*847ce401SWu Fengguang 	return 0;
58*847ce401SWu Fengguang fail:
59cae681fcSAndi Kleen 	pfn_inject_exit();
60cae681fcSAndi Kleen 	return -ENOMEM;
61cae681fcSAndi Kleen }
62cae681fcSAndi Kleen 
63cae681fcSAndi Kleen module_init(pfn_inject_init);
64cae681fcSAndi Kleen module_exit(pfn_inject_exit);
65cae681fcSAndi Kleen MODULE_LICENSE("GPL");
66