blob: 87dde3682f5e276085f75674ed79e167f3581c82 [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>
Akinobu Mita6a11f752009-03-31 15:23:17 -07005#include <linux/page-debug-flags.h>
6#include <linux/poison.h>
Akinobu Mita77311132011-10-31 17:08:05 -07007#include <linux/ratelimit.h>
Akinobu Mita6a11f752009-03-31 15:23:17 -07008
Laura Abbott473469842014-04-14 20:09:44 -07009#ifndef mark_addr_rdonly
10#define mark_addr_rdonly(a)
11#endif
12
13#ifndef mark_addr_rdwrite
14#define mark_addr_rdwrite(a)
15#endif
16
Akinobu Mita6a11f752009-03-31 15:23:17 -070017static inline void set_page_poison(struct page *page)
18{
19 __set_bit(PAGE_DEBUG_FLAG_POISON, &page->debug_flags);
20}
21
22static inline void clear_page_poison(struct page *page)
23{
24 __clear_bit(PAGE_DEBUG_FLAG_POISON, &page->debug_flags);
25}
26
27static inline bool page_poison(struct page *page)
28{
29 return test_bit(PAGE_DEBUG_FLAG_POISON, &page->debug_flags);
30}
31
Akinobu Mita6a11f752009-03-31 15:23:17 -070032static void poison_page(struct page *page)
33{
Akinobu Mita64212ec2011-10-31 17:08:38 -070034 void *addr = kmap_atomic(page);
Akinobu Mita6a11f752009-03-31 15:23:17 -070035
Akinobu Mita6a11f752009-03-31 15:23:17 -070036 set_page_poison(page);
Akinobu Mita6a11f752009-03-31 15:23:17 -070037 memset(addr, PAGE_POISON, PAGE_SIZE);
Laura Abbott473469842014-04-14 20:09:44 -070038 mark_addr_rdonly(addr);
Akinobu Mita64212ec2011-10-31 17:08:38 -070039 kunmap_atomic(addr);
Akinobu Mita6a11f752009-03-31 15:23:17 -070040}
41
42static void poison_pages(struct page *page, int n)
43{
44 int i;
45
46 for (i = 0; i < n; i++)
47 poison_page(page + i);
48}
49
50static bool single_bit_flip(unsigned char a, unsigned char b)
51{
52 unsigned char error = a ^ b;
53
54 return error && !(error & (error - 1));
55}
56
57static void check_poison_mem(unsigned char *mem, size_t bytes)
58{
Akinobu Mita77311132011-10-31 17:08:05 -070059 static DEFINE_RATELIMIT_STATE(ratelimit, 5 * HZ, 10);
Akinobu Mita6a11f752009-03-31 15:23:17 -070060 unsigned char *start;
61 unsigned char *end;
62
Akinobu Mita8c5fb8e2011-10-31 17:08:10 -070063 start = memchr_inv(mem, PAGE_POISON, bytes);
64 if (!start)
Akinobu Mita6a11f752009-03-31 15:23:17 -070065 return;
66
67 for (end = mem + bytes - 1; end > start; end--) {
68 if (*end != PAGE_POISON)
69 break;
70 }
71
Akinobu Mita77311132011-10-31 17:08:05 -070072 if (!__ratelimit(&ratelimit))
Akinobu Mita6a11f752009-03-31 15:23:17 -070073 return;
74 else if (start == end && single_bit_flip(*start, PAGE_POISON))
75 printk(KERN_ERR "pagealloc: single bit error\n");
76 else
77 printk(KERN_ERR "pagealloc: memory corruption\n");
78
79 print_hex_dump(KERN_ERR, "", DUMP_PREFIX_ADDRESS, 16, 1, start,
80 end - start + 1, 1);
Subbaraman Narayanamurthy66399732013-09-20 15:23:56 -070081 BUG_ON(PANIC_CORRUPTION);
Akinobu Mita6a11f752009-03-31 15:23:17 -070082 dump_stack();
83}
84
Akinobu Mita6a11f752009-03-31 15:23:17 -070085static void unpoison_page(struct page *page)
86{
Akinobu Mita64212ec2011-10-31 17:08:38 -070087 void *addr;
Akinobu Mita6a11f752009-03-31 15:23:17 -070088
Akinobu Mita64212ec2011-10-31 17:08:38 -070089 if (!page_poison(page))
90 return;
91
92 addr = kmap_atomic(page);
93 check_poison_mem(addr, PAGE_SIZE);
Laura Abbott473469842014-04-14 20:09:44 -070094 mark_addr_rdwrite(addr);
Akinobu Mita64212ec2011-10-31 17:08:38 -070095 clear_page_poison(page);
96 kunmap_atomic(addr);
Akinobu Mita6a11f752009-03-31 15:23:17 -070097}
98
99static void unpoison_pages(struct page *page, int n)
100{
101 int i;
102
103 for (i = 0; i < n; i++)
104 unpoison_page(page + i);
105}
106
107void kernel_map_pages(struct page *page, int numpages, int enable)
108{
Akinobu Mita6a11f752009-03-31 15:23:17 -0700109 if (enable)
110 unpoison_pages(page, numpages);
111 else
112 poison_pages(page, numpages);
113}