Blame view
mm/debug-pagealloc.c
2.05 KB
6a11f75b6 generic debug pag... |
1 |
#include <linux/kernel.h> |
8c5fb8ead mm/debug-pageallo... |
2 |
#include <linux/string.h> |
6a11f75b6 generic debug pag... |
3 |
#include <linux/mm.h> |
64212ec56 debug-pagealloc: ... |
4 |
#include <linux/highmem.h> |
6a11f75b6 generic debug pag... |
5 6 |
#include <linux/page-debug-flags.h> #include <linux/poison.h> |
77311139f mm/debug-pageallo... |
7 |
#include <linux/ratelimit.h> |
6a11f75b6 generic debug pag... |
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
static inline void set_page_poison(struct page *page) { __set_bit(PAGE_DEBUG_FLAG_POISON, &page->debug_flags); } static inline void clear_page_poison(struct page *page) { __clear_bit(PAGE_DEBUG_FLAG_POISON, &page->debug_flags); } static inline bool page_poison(struct page *page) { return test_bit(PAGE_DEBUG_FLAG_POISON, &page->debug_flags); } |
6a11f75b6 generic debug pag... |
23 24 |
static void poison_page(struct page *page) { |
64212ec56 debug-pagealloc: ... |
25 |
void *addr = kmap_atomic(page); |
6a11f75b6 generic debug pag... |
26 |
|
6a11f75b6 generic debug pag... |
27 |
set_page_poison(page); |
6a11f75b6 generic debug pag... |
28 |
memset(addr, PAGE_POISON, PAGE_SIZE); |
64212ec56 debug-pagealloc: ... |
29 |
kunmap_atomic(addr); |
6a11f75b6 generic debug pag... |
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
} static void poison_pages(struct page *page, int n) { int i; for (i = 0; i < n; i++) poison_page(page + i); } static bool single_bit_flip(unsigned char a, unsigned char b) { unsigned char error = a ^ b; return error && !(error & (error - 1)); } static void check_poison_mem(unsigned char *mem, size_t bytes) { |
77311139f mm/debug-pageallo... |
49 |
static DEFINE_RATELIMIT_STATE(ratelimit, 5 * HZ, 10); |
6a11f75b6 generic debug pag... |
50 51 |
unsigned char *start; unsigned char *end; |
8c5fb8ead mm/debug-pageallo... |
52 53 |
start = memchr_inv(mem, PAGE_POISON, bytes); if (!start) |
6a11f75b6 generic debug pag... |
54 55 56 57 58 59 |
return; for (end = mem + bytes - 1; end > start; end--) { if (*end != PAGE_POISON) break; } |
77311139f mm/debug-pageallo... |
60 |
if (!__ratelimit(&ratelimit)) |
6a11f75b6 generic debug pag... |
61 62 63 64 65 66 67 68 69 70 71 72 |
return; else if (start == end && single_bit_flip(*start, PAGE_POISON)) printk(KERN_ERR "pagealloc: single bit error "); else printk(KERN_ERR "pagealloc: memory corruption "); print_hex_dump(KERN_ERR, "", DUMP_PREFIX_ADDRESS, 16, 1, start, end - start + 1, 1); dump_stack(); } |
6a11f75b6 generic debug pag... |
73 74 |
static void unpoison_page(struct page *page) { |
64212ec56 debug-pagealloc: ... |
75 76 77 |
void *addr; if (!page_poison(page)) |
6a11f75b6 generic debug pag... |
78 |
return; |
6a11f75b6 generic debug pag... |
79 |
|
64212ec56 debug-pagealloc: ... |
80 81 82 83 |
addr = kmap_atomic(page); check_poison_mem(addr, PAGE_SIZE); clear_page_poison(page); kunmap_atomic(addr); |
6a11f75b6 generic debug pag... |
84 85 86 87 88 89 90 91 92 93 94 95 |
} static void unpoison_pages(struct page *page, int n) { int i; for (i = 0; i < n; i++) unpoison_page(page + i); } void kernel_map_pages(struct page *page, int numpages, int enable) { |
6a11f75b6 generic debug pag... |
96 97 98 99 100 |
if (enable) unpoison_pages(page, numpages); else poison_pages(page, numpages); } |