debug-pagealloc.c 2.2 KB

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