1#include <linux/kernel.h> 2#include <linux/string.h> 3#include <linux/mm.h> 4#include <linux/highmem.h> 5#include <linux/page_ext.h> 6#include <linux/poison.h> 7#include <linux/ratelimit.h> 8 9static bool page_poisoning_enabled __read_mostly; 10 11static bool need_page_poisoning(void) 12{ 13 if (!debug_pagealloc_enabled()) 14 return false; 15 16 return true; 17} 18 19static void init_page_poisoning(void) 20{ 21 if (!debug_pagealloc_enabled()) 22 return; 23 24 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 32static inline void set_page_poison(struct page *page) 33{ 34 struct page_ext *page_ext; 35 36 page_ext = lookup_page_ext(page); 37 __set_bit(PAGE_EXT_DEBUG_POISON, &page_ext->flags); 38} 39 40static inline void clear_page_poison(struct page *page) 41{ 42 struct page_ext *page_ext; 43 44 page_ext = lookup_page_ext(page); 45 __clear_bit(PAGE_EXT_DEBUG_POISON, &page_ext->flags); 46} 47 48static inline bool page_poison(struct page *page) 49{ 50 struct page_ext *page_ext; 51 52 page_ext = lookup_page_ext(page); 53 return test_bit(PAGE_EXT_DEBUG_POISON, &page_ext->flags); 54} 55 56static void poison_page(struct page *page) 57{ 58 void *addr = kmap_atomic(page); 59 60 set_page_poison(page); 61 memset(addr, PAGE_POISON, PAGE_SIZE); 62 kunmap_atomic(addr); 63} 64 65static void poison_pages(struct page *page, int n) 66{ 67 int i; 68 69 for (i = 0; i < n; i++) 70 poison_page(page + i); 71} 72 73static bool single_bit_flip(unsigned char a, unsigned char b) 74{ 75 unsigned char error = a ^ b; 76 77 return error && !(error & (error - 1)); 78} 79 80static void check_poison_mem(unsigned char *mem, size_t bytes) 81{ 82 static DEFINE_RATELIMIT_STATE(ratelimit, 5 * HZ, 10); 83 unsigned char *start; 84 unsigned char *end; 85 86 start = memchr_inv(mem, PAGE_POISON, bytes); 87 if (!start) 88 return; 89 90 for (end = mem + bytes - 1; end > start; end--) { 91 if (*end != PAGE_POISON) 92 break; 93 } 94 95 if (!__ratelimit(&ratelimit)) 96 return; 97 else if (start == end && single_bit_flip(*start, PAGE_POISON)) 98 printk(KERN_ERR "pagealloc: single bit error\n"); 99 else 100 printk(KERN_ERR "pagealloc: memory corruption\n"); 101 102 print_hex_dump(KERN_ERR, "", DUMP_PREFIX_ADDRESS, 16, 1, start, 103 end - start + 1, 1); 104 dump_stack(); 105} 106 107static void unpoison_page(struct page *page) 108{ 109 void *addr; 110 111 if (!page_poison(page)) 112 return; 113 114 addr = kmap_atomic(page); 115 check_poison_mem(addr, PAGE_SIZE); 116 clear_page_poison(page); 117 kunmap_atomic(addr); 118} 119 120static void unpoison_pages(struct page *page, int n) 121{ 122 int i; 123 124 for (i = 0; i < n; i++) 125 unpoison_page(page + i); 126} 127 128void __kernel_map_pages(struct page *page, int numpages, int enable) 129{ 130 if (!page_poisoning_enabled) 131 return; 132 133 if (enable) 134 unpoison_pages(page, numpages); 135 else 136 poison_pages(page, numpages); 137} 138