blob: fe1c61f7cf26203d71f3fb12151c34b2b1b831cb [file] [log] [blame]
Akinobu Mita6a11f752009-03-31 15:23:17 -07001#include <linux/kernel.h>
Akinobu Mita8c5fb8e2011-10-31 17:08:10 -07002#include <linux/string.h>
Akinobu Mita6a11f752009-03-31 15:23:17 -07003#include <linux/mm.h>
Akinobu Mita64212ec2011-10-31 17:08:38 -07004#include <linux/highmem.h>
Joonsoo Kime30825f2014-12-12 16:55:49 -08005#include <linux/page_ext.h>
Akinobu Mita6a11f752009-03-31 15:23:17 -07006#include <linux/poison.h>
Akinobu Mita77311132011-10-31 17:08:05 -07007#include <linux/ratelimit.h>
Akinobu Mita6a11f752009-03-31 15:23:17 -07008
Joonsoo Kime30825f2014-12-12 16:55:49 -08009static bool page_poisoning_enabled __read_mostly;
10
11static bool need_page_poisoning(void)
12{
Joonsoo Kim031bc572014-12-12 16:55:52 -080013 if (!debug_pagealloc_enabled())
14 return false;
15
Joonsoo Kime30825f2014-12-12 16:55:49 -080016 return true;
17}
18
19static void init_page_poisoning(void)
20{
Joonsoo Kim031bc572014-12-12 16:55:52 -080021 if (!debug_pagealloc_enabled())
22 return;
23
Joonsoo Kime30825f2014-12-12 16:55:49 -080024 page_poisoning_enabled = true;
25}
26
27struct page_ext_operations page_poisoning_ops = {
28 .need = need_page_poisoning,
29 .init = init_page_poisoning,
30};
31
Akinobu Mita6a11f752009-03-31 15:23:17 -070032static inline void set_page_poison(struct page *page)
33{
Joonsoo Kime30825f2014-12-12 16:55:49 -080034 struct page_ext *page_ext;
35
36 page_ext = lookup_page_ext(page);
Yang Shie34e7442016-06-03 14:55:38 -070037 if (page_ext)
38 return;
Joonsoo Kime30825f2014-12-12 16:55:49 -080039 __set_bit(PAGE_EXT_DEBUG_POISON, &page_ext->flags);
Akinobu Mita6a11f752009-03-31 15:23:17 -070040}
41
42static inline void clear_page_poison(struct page *page)
43{
Joonsoo Kime30825f2014-12-12 16:55:49 -080044 struct page_ext *page_ext;
45
46 page_ext = lookup_page_ext(page);
Yang Shie34e7442016-06-03 14:55:38 -070047 if (page_ext)
48 return;
Joonsoo Kime30825f2014-12-12 16:55:49 -080049 __clear_bit(PAGE_EXT_DEBUG_POISON, &page_ext->flags);
Akinobu Mita6a11f752009-03-31 15:23:17 -070050}
51
52static inline bool page_poison(struct page *page)
53{
Joonsoo Kime30825f2014-12-12 16:55:49 -080054 struct page_ext *page_ext;
55
56 page_ext = lookup_page_ext(page);
Yang Shie34e7442016-06-03 14:55:38 -070057 if (page_ext)
58 return false;
Joonsoo Kime30825f2014-12-12 16:55:49 -080059 return test_bit(PAGE_EXT_DEBUG_POISON, &page_ext->flags);
Akinobu Mita6a11f752009-03-31 15:23:17 -070060}
61
Akinobu Mita6a11f752009-03-31 15:23:17 -070062static void poison_page(struct page *page)
63{
Akinobu Mita64212ec2011-10-31 17:08:38 -070064 void *addr = kmap_atomic(page);
Akinobu Mita6a11f752009-03-31 15:23:17 -070065
Akinobu Mita6a11f752009-03-31 15:23:17 -070066 set_page_poison(page);
Akinobu Mita6a11f752009-03-31 15:23:17 -070067 memset(addr, PAGE_POISON, PAGE_SIZE);
Akinobu Mita64212ec2011-10-31 17:08:38 -070068 kunmap_atomic(addr);
Akinobu Mita6a11f752009-03-31 15:23:17 -070069}
70
71static void poison_pages(struct page *page, int n)
72{
73 int i;
74
75 for (i = 0; i < n; i++)
76 poison_page(page + i);
77}
78
79static bool single_bit_flip(unsigned char a, unsigned char b)
80{
81 unsigned char error = a ^ b;
82
83 return error && !(error & (error - 1));
84}
85
86static void check_poison_mem(unsigned char *mem, size_t bytes)
87{
Akinobu Mita77311132011-10-31 17:08:05 -070088 static DEFINE_RATELIMIT_STATE(ratelimit, 5 * HZ, 10);
Akinobu Mita6a11f752009-03-31 15:23:17 -070089 unsigned char *start;
90 unsigned char *end;
91
Akinobu Mita8c5fb8e2011-10-31 17:08:10 -070092 start = memchr_inv(mem, PAGE_POISON, bytes);
93 if (!start)
Akinobu Mita6a11f752009-03-31 15:23:17 -070094 return;
95
96 for (end = mem + bytes - 1; end > start; end--) {
97 if (*end != PAGE_POISON)
98 break;
99 }
100
Akinobu Mita77311132011-10-31 17:08:05 -0700101 if (!__ratelimit(&ratelimit))
Akinobu Mita6a11f752009-03-31 15:23:17 -0700102 return;
103 else if (start == end && single_bit_flip(*start, PAGE_POISON))
104 printk(KERN_ERR "pagealloc: single bit error\n");
105 else
106 printk(KERN_ERR "pagealloc: memory corruption\n");
107
108 print_hex_dump(KERN_ERR, "", DUMP_PREFIX_ADDRESS, 16, 1, start,
109 end - start + 1, 1);
110 dump_stack();
111}
112
Akinobu Mita6a11f752009-03-31 15:23:17 -0700113static void unpoison_page(struct page *page)
114{
Akinobu Mita64212ec2011-10-31 17:08:38 -0700115 void *addr;
Akinobu Mita6a11f752009-03-31 15:23:17 -0700116
Akinobu Mita64212ec2011-10-31 17:08:38 -0700117 if (!page_poison(page))
118 return;
119
120 addr = kmap_atomic(page);
121 check_poison_mem(addr, PAGE_SIZE);
122 clear_page_poison(page);
123 kunmap_atomic(addr);
Akinobu Mita6a11f752009-03-31 15:23:17 -0700124}
125
126static void unpoison_pages(struct page *page, int n)
127{
128 int i;
129
130 for (i = 0; i < n; i++)
131 unpoison_page(page + i);
132}
133
Joonsoo Kim031bc572014-12-12 16:55:52 -0800134void __kernel_map_pages(struct page *page, int numpages, int enable)
Akinobu Mita6a11f752009-03-31 15:23:17 -0700135{
Joonsoo Kime30825f2014-12-12 16:55:49 -0800136 if (!page_poisoning_enabled)
137 return;
138
Akinobu Mita6a11f752009-03-31 15:23:17 -0700139 if (enable)
140 unpoison_pages(page, numpages);
141 else
142 poison_pages(page, numpages);
143}