summaryrefslogtreecommitdiff
path: root/mm
diff options
context:
space:
mode:
authorStephen Rothwell <sfr@canb.auug.org.au>2016-09-29 11:39:31 +1000
committerStephen Rothwell <sfr@canb.auug.org.au>2016-09-29 11:39:31 +1000
commit4d8759d644731cd0bc5c52352498c2bca2d928e3 (patch)
treecea3e8a08d8a851546e972bdbfeffa7668af1678 /mm
parent657d91dac15f0e758ce5a78608c70c68f5a836a9 (diff)
parent09dd109d8241cd570391d4488337b77a4525f24e (diff)
Merge remote-tracking branch 'kspp/for-next/kspp'
Diffstat (limited to 'mm')
-rw-r--r--mm/page_alloc.c26
1 files changed, 26 insertions, 0 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index a2214c64ed3c..41940f6e3c1c 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -64,6 +64,7 @@
#include <linux/page_owner.h>
#include <linux/kthread.h>
#include <linux/memcontrol.h>
+#include <linux/random.h>
#include <asm/sections.h>
#include <asm/tlbflush.h>
@@ -91,6 +92,11 @@ EXPORT_PER_CPU_SYMBOL(_numa_mem_);
int _node_numa_mem_[MAX_NUMNODES];
#endif
+#ifdef CONFIG_GCC_PLUGIN_LATENT_ENTROPY
+volatile u64 latent_entropy __latent_entropy;
+EXPORT_SYMBOL(latent_entropy);
+#endif
+
/*
* Array of node states.
*/
@@ -1234,6 +1240,15 @@ static void __free_pages_ok(struct page *page, unsigned int order)
local_irq_restore(flags);
}
+bool __meminitdata ram_latent_entropy;
+
+static int __init setup_ram_latent_entropy(char *str)
+{
+ ram_latent_entropy = true;
+ return 0;
+}
+early_param("ram_latent_entropy", setup_ram_latent_entropy);
+
static void __init __free_pages_boot_core(struct page *page, unsigned int order)
{
unsigned int nr_pages = 1 << order;
@@ -1249,6 +1264,17 @@ static void __init __free_pages_boot_core(struct page *page, unsigned int order)
__ClearPageReserved(p);
set_page_count(p, 0);
+ if (ram_latent_entropy && !PageHighMem(page) &&
+ page_to_pfn(page) < 0x100000) {
+ u64 hash = 0;
+ size_t index, end = PAGE_SIZE * nr_pages / sizeof(hash);
+ const u64 *data = lowmem_page_address(page);
+
+ for (index = 0; index < end; index++)
+ hash ^= hash + data[index];
+ add_device_randomness((const void *)&hash, sizeof(hash));
+ }
+
page_zone(page)->managed_pages += nr_pages;
set_page_refcounted(page);
__free_pages(page, order);