unsigned long size, pte_fn_t fn, void *data);
 
 
+#ifdef CONFIG_PAGE_POISONING
+extern bool page_poisoning_enabled(void);
+extern void kernel_poison_pages(struct page *page, int numpages, int enable);
+#else
+static inline bool page_poisoning_enabled(void) { return false; }
+static inline void kernel_poison_pages(struct page *page, int numpages,
+                                       int enable) { }
+#endif
+
 #ifdef CONFIG_DEBUG_PAGEALLOC
 extern bool _debug_pagealloc_enabled;
 extern void __kernel_map_pages(struct page *page, int numpages, int enable);
 
          can be overridden by debug_pagealloc=off|on.
 
 config PAGE_POISONING
-       bool
+       bool "Poison pages after freeing"
+       select PAGE_EXTENSION
+       select PAGE_POISONING_NO_SANITY if HIBERNATION
+       ---help---
+         Fill the pages with poison patterns after free_pages() and verify
+         the patterns before alloc_pages. The filling of the memory helps
+         reduce the risk of information leaks from freed data. This does
+         have a potential performance impact.
+
+         Note that "poison" here is not the same thing as the "HWPoison"
+         for CONFIG_MEMORY_FAILURE. This is software poisoning only.
+
+         If unsure, say N
+
+config PAGE_POISONING_NO_SANITY
+       depends on PAGE_POISONING
+       bool "Only poison, don't sanity check"
+       ---help---
+          Skip the sanity checking on alloc, only fill the pages with
+          poison on free. This reduces some of the overhead of the
+          poisoning feature.
+
+          If you are only interested in sanitization, say Y. Otherwise
+          say N.
 
                                           PAGE_SIZE << order);
        }
        arch_free_page(page, order);
+       kernel_poison_pages(page, 1 << order, 0);
        kernel_map_pages(page, 1 << order, 0);
 
        return true;
 
        arch_alloc_page(page, order);
        kernel_map_pages(page, 1 << order, 1);
+       kernel_poison_pages(page, 1 << order, 1);
        kasan_alloc_pages(page, order);
 
        if (gfp_flags & __GFP_ZERO)
 
 #include <linux/poison.h>
 #include <linux/ratelimit.h>
 
-static bool page_poisoning_enabled __read_mostly;
+static bool __page_poisoning_enabled __read_mostly;
+static bool want_page_poisoning __read_mostly;
 
-static bool need_page_poisoning(void)
+static int early_page_poison_param(char *buf)
 {
-       if (!debug_pagealloc_enabled())
-               return false;
+       if (!buf)
+               return -EINVAL;
+
+       if (strcmp(buf, "on") == 0)
+               want_page_poisoning = true;
+       else if (strcmp(buf, "off") == 0)
+               want_page_poisoning = false;
 
-       return true;
+       return 0;
+}
+early_param("page_poison", early_page_poison_param);
+
+bool page_poisoning_enabled(void)
+{
+       return __page_poisoning_enabled;
+}
+
+static bool need_page_poisoning(void)
+{
+       return want_page_poisoning;
 }
 
 static void init_page_poisoning(void)
 {
-       if (!debug_pagealloc_enabled())
-               return;
+       /*
+        * page poisoning is debug page alloc for some arches. If either
+        * of those options are enabled, enable poisoning
+        */
+       if (!IS_ENABLED(CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC)) {
+               if (!want_page_poisoning && !debug_pagealloc_enabled())
+                       return;
+       } else {
+               if (!want_page_poisoning)
+                       return;
+       }
 
-       page_poisoning_enabled = true;
+       __page_poisoning_enabled = true;
 }
 
 struct page_ext_operations page_poisoning_ops = {
        unsigned char *start;
        unsigned char *end;
 
+       if (IS_ENABLED(CONFIG_PAGE_POISONING_NO_SANITY))
+               return;
+
        start = memchr_inv(mem, PAGE_POISON, bytes);
        if (!start)
                return;
        if (!__ratelimit(&ratelimit))
                return;
        else if (start == end && single_bit_flip(*start, PAGE_POISON))
-               printk(KERN_ERR "pagealloc: single bit error\n");
+               pr_err("pagealloc: single bit error\n");
        else
-               printk(KERN_ERR "pagealloc: memory corruption\n");
+               pr_err("pagealloc: memory corruption\n");
 
        print_hex_dump(KERN_ERR, "", DUMP_PREFIX_ADDRESS, 16, 1, start,
                        end - start + 1, 1);
                unpoison_page(page + i);
 }
 
-void __kernel_map_pages(struct page *page, int numpages, int enable)
+void kernel_poison_pages(struct page *page, int numpages, int enable)
 {
-       if (!page_poisoning_enabled)
+       if (!page_poisoning_enabled())
                return;
 
        if (enable)
        else
                poison_pages(page, numpages);
 }
+
+#ifndef CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC
+void __kernel_map_pages(struct page *page, int numpages, int enable)
+{
+       /* This function does nothing, all work is done via poison pages */
+}
+#endif