Blame view

mm/hwpoison-inject.c 2.63 KB
09c434b8a   Thomas Gleixner   treewide: Add SPD...
1
  // SPDX-License-Identifier: GPL-2.0-only
25985edce   Lucas De Marchi   Fix common misspe...
2
  /* Inject a hwpoison memory failure on a arbitrary pfn */
cae681fc1   Andi Kleen   HWPOISON: Add sim...
3
4
5
6
  #include <linux/module.h>
  #include <linux/debugfs.h>
  #include <linux/kernel.h>
  #include <linux/mm.h>
31d3d3484   Wu Fengguang   HWPOISON: limit h...
7
8
  #include <linux/swap.h>
  #include <linux/pagemap.h>
43131e141   Naoya Horiguchi   HWPOISON, hugetlb...
9
  #include <linux/hugetlb.h>
7c116f2b0   Wu Fengguang   HWPOISON: add fs/...
10
  #include "internal.h"
cae681fc1   Andi Kleen   HWPOISON: Add sim...
11

847ce401d   Wu Fengguang   HWPOISON: Add unp...
12
  static struct dentry *hwpoison_dir;
cae681fc1   Andi Kleen   HWPOISON: Add sim...
13
14
15
  
  static int hwpoison_inject(void *data, u64 val)
  {
31d3d3484   Wu Fengguang   HWPOISON: limit h...
16
17
  	unsigned long pfn = val;
  	struct page *p;
43131e141   Naoya Horiguchi   HWPOISON, hugetlb...
18
  	struct page *hpage;
31d3d3484   Wu Fengguang   HWPOISON: limit h...
19
  	int err;
cae681fc1   Andi Kleen   HWPOISON: Add sim...
20
21
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
31d3d3484   Wu Fengguang   HWPOISON: limit h...
22
23
24
25
26
  
  	if (!pfn_valid(pfn))
  		return -ENXIO;
  
  	p = pfn_to_page(pfn);
43131e141   Naoya Horiguchi   HWPOISON, hugetlb...
27
  	hpage = compound_head(p);
31d3d3484   Wu Fengguang   HWPOISON: limit h...
28

fb31ba30f   Wanpeng Li   mm/hwpoison: fix ...
29
30
  	if (!hwpoison_filter_enable)
  		goto inject;
8bcb74de7   Naoya Horiguchi   mm: hwpoison: cal...
31
  	shake_page(hpage, 0);
31d3d3484   Wu Fengguang   HWPOISON: limit h...
32
33
34
  	/*
  	 * This implies unable to support non-LRU pages.
  	 */
e386eed89   Naoya Horiguchi   mm/hwpoison-injec...
35
  	if (!PageLRU(hpage) && !PageHuge(p))
fd476720c   Naoya Horiguchi   mm,hwpoison-injec...
36
  		return 0;
31d3d3484   Wu Fengguang   HWPOISON: limit h...
37
38
  
  	/*
fd476720c   Naoya Horiguchi   mm,hwpoison-injec...
39
40
  	 * do a racy check to make sure PG_hwpoison will only be set for
  	 * the targeted owner (or on a free page).
cd42f4a3b   Tony Luck   HWPOISON: Clean u...
41
  	 * memory_failure() will redo the check reliably inside page lock.
31d3d3484   Wu Fengguang   HWPOISON: limit h...
42
  	 */
43131e141   Naoya Horiguchi   HWPOISON, hugetlb...
43
  	err = hwpoison_filter(hpage);
31d3d3484   Wu Fengguang   HWPOISON: limit h...
44
  	if (err)
fd476720c   Naoya Horiguchi   mm,hwpoison-injec...
45
  		return 0;
31d3d3484   Wu Fengguang   HWPOISON: limit h...
46

0d57eb8df   Andi Kleen   HWPOISON: Don't d...
47
  inject:
4883e997b   Wanpeng Li   mm/hwpoison: add ...
48
49
  	pr_info("Injecting memory failure at pfn %#lx
  ", pfn);
fd476720c   Naoya Horiguchi   mm,hwpoison-injec...
50
  	return memory_failure(pfn, 0);
cae681fc1   Andi Kleen   HWPOISON: Add sim...
51
  }
847ce401d   Wu Fengguang   HWPOISON: Add unp...
52
53
54
55
56
57
58
  static int hwpoison_unpoison(void *data, u64 val)
  {
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
  
  	return unpoison_memory(val);
  }
35e3d566d   zhong jiang   mm/hwpoison-injec...
59
60
61
62
  DEFINE_DEBUGFS_ATTRIBUTE(hwpoison_fops, NULL, hwpoison_inject, "%lli
  ");
  DEFINE_DEBUGFS_ATTRIBUTE(unpoison_fops, NULL, hwpoison_unpoison, "%lli
  ");
cae681fc1   Andi Kleen   HWPOISON: Add sim...
63
64
65
  
  static void pfn_inject_exit(void)
  {
c2ea2181d   Fabian Frederick   mm/hwpoison-injec...
66
  	debugfs_remove_recursive(hwpoison_dir);
cae681fc1   Andi Kleen   HWPOISON: Add sim...
67
68
69
70
71
  }
  
  static int pfn_inject_init(void)
  {
  	hwpoison_dir = debugfs_create_dir("hwpoison", NULL);
847ce401d   Wu Fengguang   HWPOISON: Add unp...
72
73
74
75
76
77
  
  	/*
  	 * Note that the below poison/unpoison interfaces do not involve
  	 * hardware status change, hence do not require hardware support.
  	 * They are mainly for testing hwpoison in software level.
  	 */
2fcc6e202   Greg Kroah-Hartman   hwpoison-inject: ...
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
  	debugfs_create_file("corrupt-pfn", 0200, hwpoison_dir, NULL,
  			    &hwpoison_fops);
  
  	debugfs_create_file("unpoison-pfn", 0200, hwpoison_dir, NULL,
  			    &unpoison_fops);
  
  	debugfs_create_u32("corrupt-filter-enable", 0600, hwpoison_dir,
  			   &hwpoison_filter_enable);
  
  	debugfs_create_u32("corrupt-filter-dev-major", 0600, hwpoison_dir,
  			   &hwpoison_filter_dev_major);
  
  	debugfs_create_u32("corrupt-filter-dev-minor", 0600, hwpoison_dir,
  			   &hwpoison_filter_dev_minor);
  
  	debugfs_create_u64("corrupt-filter-flags-mask", 0600, hwpoison_dir,
  			   &hwpoison_filter_flags_mask);
  
  	debugfs_create_u64("corrupt-filter-flags-value", 0600, hwpoison_dir,
  			   &hwpoison_filter_flags_value);
478c5ffc0   Wu Fengguang   HWPOISON: add pag...
98

94a59fb36   Vladimir Davydov   hwpoison: use pag...
99
  #ifdef CONFIG_MEMCG
2fcc6e202   Greg Kroah-Hartman   hwpoison-inject: ...
100
101
  	debugfs_create_u64("corrupt-filter-memcg", 0600, hwpoison_dir,
  			   &hwpoison_filter_memcg);
4fd466eb4   Andi Kleen   HWPOISON: add mem...
102
  #endif
cae681fc1   Andi Kleen   HWPOISON: Add sim...
103
104
105
106
107
108
  	return 0;
  }
  
  module_init(pfn_inject_init);
  module_exit(pfn_inject_exit);
  MODULE_LICENSE("GPL");