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