Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v6.17-rc2 114 lines 2.9 kB view raw
1// SPDX-License-Identifier: GPL-2.0-only 2/* Inject a hwpoison memory failure on a arbitrary pfn */ 3#include <linux/module.h> 4#include <linux/debugfs.h> 5#include <linux/kernel.h> 6#include <linux/mm.h> 7#include <linux/swap.h> 8#include <linux/pagemap.h> 9#include <linux/hugetlb.h> 10#include "internal.h" 11 12static struct dentry *hwpoison_dir; 13 14static int hwpoison_inject(void *data, u64 val) 15{ 16 unsigned long pfn = val; 17 struct page *p; 18 struct folio *folio; 19 int err; 20 21 if (!capable(CAP_SYS_ADMIN)) 22 return -EPERM; 23 24 if (!pfn_valid(pfn)) 25 return -ENXIO; 26 27 p = pfn_to_page(pfn); 28 folio = page_folio(p); 29 30 if (!hwpoison_filter_enable) 31 goto inject; 32 33 shake_folio(folio); 34 /* 35 * This implies unable to support non-LRU pages except free page. 36 */ 37 if (!folio_test_lru(folio) && !folio_test_hugetlb(folio) && 38 !is_free_buddy_page(p)) 39 return 0; 40 41 /* 42 * do a racy check to make sure PG_hwpoison will only be set for 43 * the targeted owner (or on a free page). 44 * memory_failure() will redo the check reliably inside page lock. 45 */ 46 err = hwpoison_filter(&folio->page); 47 if (err) 48 return 0; 49 50inject: 51 pr_info("Injecting memory failure at pfn %#lx\n", pfn); 52 err = memory_failure(pfn, MF_SW_SIMULATED); 53 return (err == -EOPNOTSUPP) ? 0 : err; 54} 55 56static int hwpoison_unpoison(void *data, u64 val) 57{ 58 if (!capable(CAP_SYS_ADMIN)) 59 return -EPERM; 60 61 return unpoison_memory(val); 62} 63 64DEFINE_DEBUGFS_ATTRIBUTE(hwpoison_fops, NULL, hwpoison_inject, "%lli\n"); 65DEFINE_DEBUGFS_ATTRIBUTE(unpoison_fops, NULL, hwpoison_unpoison, "%lli\n"); 66 67static void __exit pfn_inject_exit(void) 68{ 69 hwpoison_filter_enable = 0; 70 debugfs_remove_recursive(hwpoison_dir); 71} 72 73static int __init pfn_inject_init(void) 74{ 75 hwpoison_dir = debugfs_create_dir("hwpoison", NULL); 76 77 /* 78 * Note that the below poison/unpoison interfaces do not involve 79 * hardware status change, hence do not require hardware support. 80 * They are mainly for testing hwpoison in software level. 81 */ 82 debugfs_create_file("corrupt-pfn", 0200, hwpoison_dir, NULL, 83 &hwpoison_fops); 84 85 debugfs_create_file("unpoison-pfn", 0200, hwpoison_dir, NULL, 86 &unpoison_fops); 87 88 debugfs_create_u32("corrupt-filter-enable", 0600, hwpoison_dir, 89 &hwpoison_filter_enable); 90 91 debugfs_create_u32("corrupt-filter-dev-major", 0600, hwpoison_dir, 92 &hwpoison_filter_dev_major); 93 94 debugfs_create_u32("corrupt-filter-dev-minor", 0600, hwpoison_dir, 95 &hwpoison_filter_dev_minor); 96 97 debugfs_create_u64("corrupt-filter-flags-mask", 0600, hwpoison_dir, 98 &hwpoison_filter_flags_mask); 99 100 debugfs_create_u64("corrupt-filter-flags-value", 0600, hwpoison_dir, 101 &hwpoison_filter_flags_value); 102 103#ifdef CONFIG_MEMCG 104 debugfs_create_u64("corrupt-filter-memcg", 0600, hwpoison_dir, 105 &hwpoison_filter_memcg); 106#endif 107 108 return 0; 109} 110 111module_init(pfn_inject_init); 112module_exit(pfn_inject_exit); 113MODULE_DESCRIPTION("HWPoison pages injector"); 114MODULE_LICENSE("GPL");