// SPDX-License-Identifier: GPL-2.0 // Copyright(c) 2018 Intel Corporation. All rights reserved. #include <linux/mm.h> #include <linux/init.h> #include <linux/mmzone.h> #include <linux/random.h> #include <linux/moduleparam.h> #include "internal.h" #include "shuffle.h" DEFINE_STATIC_KEY_FALSE(page_alloc_shuffle_key); static bool shuffle_param; static __meminit int shuffle_param_set(const char *val, const struct kernel_param *kp) { … } static const struct kernel_param_ops shuffle_param_ops = …; module_param_cb(…); /* * For two pages to be swapped in the shuffle, they must be free (on a * 'free_area' lru), have the same order, and have the same migratetype. */ static struct page * __meminit shuffle_valid_page(struct zone *zone, unsigned long pfn, int order) { … } /* * Fisher-Yates shuffle the freelist which prescribes iterating through an * array, pfns in this case, and randomly swapping each entry with another in * the span, end_pfn - start_pfn. * * To keep the implementation simple it does not attempt to correct for sources * of bias in the distribution, like modulo bias or pseudo-random number * generator bias. I.e. the expectation is that this shuffling raises the bar * for attacks that exploit the predictability of page allocations, but need not * be a perfect shuffle. */ #define SHUFFLE_RETRY … void __meminit __shuffle_zone(struct zone *z) { … } /* * __shuffle_free_memory - reduce the predictability of the page allocator * @pgdat: node page data */ void __meminit __shuffle_free_memory(pg_data_t *pgdat) { … } bool shuffle_pick_tail(void) { … }