xref: /linux/tools/testing/selftests/mm/hugepage_settings.c (revision 3d5e48944e824bddc20d7b874e784f7b279636fe)
181afb1eeSMike Rapoport (Microsoft) // SPDX-License-Identifier: GPL-2.0
21bdc1698SMike Rapoport (Microsoft) #include <dirent.h>
381afb1eeSMike Rapoport (Microsoft) #include <fcntl.h>
481afb1eeSMike Rapoport (Microsoft) #include <limits.h>
581afb1eeSMike Rapoport (Microsoft) #include <signal.h>
61bdc1698SMike Rapoport (Microsoft) #include <stddef.h>
781afb1eeSMike Rapoport (Microsoft) #include <stdio.h>
881afb1eeSMike Rapoport (Microsoft) #include <stdlib.h>
981afb1eeSMike Rapoport (Microsoft) #include <string.h>
1081afb1eeSMike Rapoport (Microsoft) #include <unistd.h>
1181afb1eeSMike Rapoport (Microsoft) 
1281afb1eeSMike Rapoport (Microsoft) #include "vm_util.h"
1381afb1eeSMike Rapoport (Microsoft) #include "hugepage_settings.h"
1481afb1eeSMike Rapoport (Microsoft) 
1581afb1eeSMike Rapoport (Microsoft) #define THP_SYSFS "/sys/kernel/mm/transparent_hugepage/"
1681afb1eeSMike Rapoport (Microsoft) #define MAX_SETTINGS_DEPTH 4
1781afb1eeSMike Rapoport (Microsoft) static struct thp_settings settings_stack[MAX_SETTINGS_DEPTH];
1881afb1eeSMike Rapoport (Microsoft) static int settings_index;
1981afb1eeSMike Rapoport (Microsoft) static struct thp_settings saved_settings;
2081afb1eeSMike Rapoport (Microsoft) static char dev_queue_read_ahead_path[PATH_MAX];
2181afb1eeSMike Rapoport (Microsoft) static bool thp_settings_saved;
2281afb1eeSMike Rapoport (Microsoft) 
2381afb1eeSMike Rapoport (Microsoft) static const char * const thp_enabled_strings[] = {
2481afb1eeSMike Rapoport (Microsoft) 	"never",
2581afb1eeSMike Rapoport (Microsoft) 	"always",
2681afb1eeSMike Rapoport (Microsoft) 	"inherit",
2781afb1eeSMike Rapoport (Microsoft) 	"madvise",
2881afb1eeSMike Rapoport (Microsoft) 	NULL
2981afb1eeSMike Rapoport (Microsoft) };
3081afb1eeSMike Rapoport (Microsoft) 
3181afb1eeSMike Rapoport (Microsoft) static const char * const thp_defrag_strings[] = {
3281afb1eeSMike Rapoport (Microsoft) 	"always",
3381afb1eeSMike Rapoport (Microsoft) 	"defer",
3481afb1eeSMike Rapoport (Microsoft) 	"defer+madvise",
3581afb1eeSMike Rapoport (Microsoft) 	"madvise",
3681afb1eeSMike Rapoport (Microsoft) 	"never",
3781afb1eeSMike Rapoport (Microsoft) 	NULL
3881afb1eeSMike Rapoport (Microsoft) };
3981afb1eeSMike Rapoport (Microsoft) 
4081afb1eeSMike Rapoport (Microsoft) static const char * const shmem_enabled_strings[] = {
4181afb1eeSMike Rapoport (Microsoft) 	"never",
4281afb1eeSMike Rapoport (Microsoft) 	"always",
4381afb1eeSMike Rapoport (Microsoft) 	"within_size",
4481afb1eeSMike Rapoport (Microsoft) 	"advise",
4581afb1eeSMike Rapoport (Microsoft) 	"inherit",
4681afb1eeSMike Rapoport (Microsoft) 	"deny",
4781afb1eeSMike Rapoport (Microsoft) 	"force",
4881afb1eeSMike Rapoport (Microsoft) 	NULL
4981afb1eeSMike Rapoport (Microsoft) };
5081afb1eeSMike Rapoport (Microsoft) 
5181afb1eeSMike Rapoport (Microsoft) int thp_read_string(const char *name, const char * const strings[])
5281afb1eeSMike Rapoport (Microsoft) {
5381afb1eeSMike Rapoport (Microsoft) 	char path[PATH_MAX];
5481afb1eeSMike Rapoport (Microsoft) 	char buf[256];
5581afb1eeSMike Rapoport (Microsoft) 	char *c;
5681afb1eeSMike Rapoport (Microsoft) 	int ret;
5781afb1eeSMike Rapoport (Microsoft) 
5881afb1eeSMike Rapoport (Microsoft) 	ret = snprintf(path, PATH_MAX, THP_SYSFS "%s", name);
5981afb1eeSMike Rapoport (Microsoft) 	if (ret >= PATH_MAX) {
6081afb1eeSMike Rapoport (Microsoft) 		printf("%s: Pathname is too long\n", __func__);
6181afb1eeSMike Rapoport (Microsoft) 		exit(EXIT_FAILURE);
6281afb1eeSMike Rapoport (Microsoft) 	}
6381afb1eeSMike Rapoport (Microsoft) 
6481afb1eeSMike Rapoport (Microsoft) 	if (!read_file(path, buf, sizeof(buf))) {
6581afb1eeSMike Rapoport (Microsoft) 		perror(path);
6681afb1eeSMike Rapoport (Microsoft) 		exit(EXIT_FAILURE);
6781afb1eeSMike Rapoport (Microsoft) 	}
6881afb1eeSMike Rapoport (Microsoft) 
6981afb1eeSMike Rapoport (Microsoft) 	c = strchr(buf, '[');
7081afb1eeSMike Rapoport (Microsoft) 	if (!c) {
7181afb1eeSMike Rapoport (Microsoft) 		printf("%s: Parse failure\n", __func__);
7281afb1eeSMike Rapoport (Microsoft) 		exit(EXIT_FAILURE);
7381afb1eeSMike Rapoport (Microsoft) 	}
7481afb1eeSMike Rapoport (Microsoft) 
7581afb1eeSMike Rapoport (Microsoft) 	c++;
7681afb1eeSMike Rapoport (Microsoft) 	memmove(buf, c, sizeof(buf) - (c - buf));
7781afb1eeSMike Rapoport (Microsoft) 
7881afb1eeSMike Rapoport (Microsoft) 	c = strchr(buf, ']');
7981afb1eeSMike Rapoport (Microsoft) 	if (!c) {
8081afb1eeSMike Rapoport (Microsoft) 		printf("%s: Parse failure\n", __func__);
8181afb1eeSMike Rapoport (Microsoft) 		exit(EXIT_FAILURE);
8281afb1eeSMike Rapoport (Microsoft) 	}
8381afb1eeSMike Rapoport (Microsoft) 	*c = '\0';
8481afb1eeSMike Rapoport (Microsoft) 
8581afb1eeSMike Rapoport (Microsoft) 	ret = 0;
8681afb1eeSMike Rapoport (Microsoft) 	while (strings[ret]) {
8781afb1eeSMike Rapoport (Microsoft) 		if (!strcmp(strings[ret], buf))
8881afb1eeSMike Rapoport (Microsoft) 			return ret;
8981afb1eeSMike Rapoport (Microsoft) 		ret++;
9081afb1eeSMike Rapoport (Microsoft) 	}
9181afb1eeSMike Rapoport (Microsoft) 
9281afb1eeSMike Rapoport (Microsoft) 	printf("Failed to parse %s\n", name);
9381afb1eeSMike Rapoport (Microsoft) 	exit(EXIT_FAILURE);
9481afb1eeSMike Rapoport (Microsoft) }
9581afb1eeSMike Rapoport (Microsoft) 
9681afb1eeSMike Rapoport (Microsoft) void thp_write_string(const char *name, const char *val)
9781afb1eeSMike Rapoport (Microsoft) {
9881afb1eeSMike Rapoport (Microsoft) 	char path[PATH_MAX];
9981afb1eeSMike Rapoport (Microsoft) 	int ret;
10081afb1eeSMike Rapoport (Microsoft) 
10181afb1eeSMike Rapoport (Microsoft) 	ret = snprintf(path, PATH_MAX, THP_SYSFS "%s", name);
10281afb1eeSMike Rapoport (Microsoft) 	if (ret >= PATH_MAX) {
10381afb1eeSMike Rapoport (Microsoft) 		printf("%s: Pathname is too long\n", __func__);
10481afb1eeSMike Rapoport (Microsoft) 		exit(EXIT_FAILURE);
10581afb1eeSMike Rapoport (Microsoft) 	}
10681afb1eeSMike Rapoport (Microsoft) 	write_file(path, val, strlen(val) + 1);
10781afb1eeSMike Rapoport (Microsoft) }
10881afb1eeSMike Rapoport (Microsoft) 
10981afb1eeSMike Rapoport (Microsoft) unsigned long thp_read_num(const char *name)
11081afb1eeSMike Rapoport (Microsoft) {
11181afb1eeSMike Rapoport (Microsoft) 	char path[PATH_MAX];
11281afb1eeSMike Rapoport (Microsoft) 	int ret;
11381afb1eeSMike Rapoport (Microsoft) 
11481afb1eeSMike Rapoport (Microsoft) 	ret = snprintf(path, PATH_MAX, THP_SYSFS "%s", name);
11581afb1eeSMike Rapoport (Microsoft) 	if (ret >= PATH_MAX) {
11681afb1eeSMike Rapoport (Microsoft) 		printf("%s: Pathname is too long\n", __func__);
11781afb1eeSMike Rapoport (Microsoft) 		exit(EXIT_FAILURE);
11881afb1eeSMike Rapoport (Microsoft) 	}
11981afb1eeSMike Rapoport (Microsoft) 	return read_num(path);
12081afb1eeSMike Rapoport (Microsoft) }
12181afb1eeSMike Rapoport (Microsoft) 
12281afb1eeSMike Rapoport (Microsoft) void thp_write_num(const char *name, unsigned long num)
12381afb1eeSMike Rapoport (Microsoft) {
12481afb1eeSMike Rapoport (Microsoft) 	char path[PATH_MAX];
12581afb1eeSMike Rapoport (Microsoft) 	int ret;
12681afb1eeSMike Rapoport (Microsoft) 
12781afb1eeSMike Rapoport (Microsoft) 	ret = snprintf(path, PATH_MAX, THP_SYSFS "%s", name);
12881afb1eeSMike Rapoport (Microsoft) 	if (ret >= PATH_MAX) {
12981afb1eeSMike Rapoport (Microsoft) 		printf("%s: Pathname is too long\n", __func__);
13081afb1eeSMike Rapoport (Microsoft) 		exit(EXIT_FAILURE);
13181afb1eeSMike Rapoport (Microsoft) 	}
13281afb1eeSMike Rapoport (Microsoft) 	write_num(path, num);
13381afb1eeSMike Rapoport (Microsoft) }
13481afb1eeSMike Rapoport (Microsoft) 
13581afb1eeSMike Rapoport (Microsoft) void thp_read_settings(struct thp_settings *settings)
13681afb1eeSMike Rapoport (Microsoft) {
13781afb1eeSMike Rapoport (Microsoft) 	unsigned long orders = thp_supported_orders();
13881afb1eeSMike Rapoport (Microsoft) 	unsigned long shmem_orders = thp_shmem_supported_orders();
13981afb1eeSMike Rapoport (Microsoft) 	char path[PATH_MAX];
14081afb1eeSMike Rapoport (Microsoft) 	int i;
14181afb1eeSMike Rapoport (Microsoft) 
14281afb1eeSMike Rapoport (Microsoft) 	*settings = (struct thp_settings) {
14381afb1eeSMike Rapoport (Microsoft) 		.thp_enabled = thp_read_string("enabled", thp_enabled_strings),
14481afb1eeSMike Rapoport (Microsoft) 		.thp_defrag = thp_read_string("defrag", thp_defrag_strings),
14581afb1eeSMike Rapoport (Microsoft) 		.shmem_enabled =
14681afb1eeSMike Rapoport (Microsoft) 			thp_read_string("shmem_enabled", shmem_enabled_strings),
14781afb1eeSMike Rapoport (Microsoft) 		.use_zero_page = thp_read_num("use_zero_page"),
14881afb1eeSMike Rapoport (Microsoft) 	};
14981afb1eeSMike Rapoport (Microsoft) 	settings->khugepaged = (struct khugepaged_settings) {
15081afb1eeSMike Rapoport (Microsoft) 		.defrag = thp_read_num("khugepaged/defrag"),
15181afb1eeSMike Rapoport (Microsoft) 		.alloc_sleep_millisecs =
15281afb1eeSMike Rapoport (Microsoft) 			thp_read_num("khugepaged/alloc_sleep_millisecs"),
15381afb1eeSMike Rapoport (Microsoft) 		.scan_sleep_millisecs =
15481afb1eeSMike Rapoport (Microsoft) 			thp_read_num("khugepaged/scan_sleep_millisecs"),
15581afb1eeSMike Rapoport (Microsoft) 		.max_ptes_none = thp_read_num("khugepaged/max_ptes_none"),
15681afb1eeSMike Rapoport (Microsoft) 		.max_ptes_swap = thp_read_num("khugepaged/max_ptes_swap"),
15781afb1eeSMike Rapoport (Microsoft) 		.max_ptes_shared = thp_read_num("khugepaged/max_ptes_shared"),
15881afb1eeSMike Rapoport (Microsoft) 		.pages_to_scan = thp_read_num("khugepaged/pages_to_scan"),
15981afb1eeSMike Rapoport (Microsoft) 	};
16081afb1eeSMike Rapoport (Microsoft) 	if (dev_queue_read_ahead_path[0])
16181afb1eeSMike Rapoport (Microsoft) 		settings->read_ahead_kb = read_num(dev_queue_read_ahead_path);
16281afb1eeSMike Rapoport (Microsoft) 
16381afb1eeSMike Rapoport (Microsoft) 	for (i = 0; i < NR_ORDERS; i++) {
16481afb1eeSMike Rapoport (Microsoft) 		if (!((1 << i) & orders)) {
16581afb1eeSMike Rapoport (Microsoft) 			settings->hugepages[i].enabled = THP_NEVER;
16681afb1eeSMike Rapoport (Microsoft) 			continue;
16781afb1eeSMike Rapoport (Microsoft) 		}
16881afb1eeSMike Rapoport (Microsoft) 		snprintf(path, PATH_MAX, "hugepages-%ukB/enabled",
16981afb1eeSMike Rapoport (Microsoft) 			(getpagesize() >> 10) << i);
17081afb1eeSMike Rapoport (Microsoft) 		settings->hugepages[i].enabled =
17181afb1eeSMike Rapoport (Microsoft) 			thp_read_string(path, thp_enabled_strings);
17281afb1eeSMike Rapoport (Microsoft) 	}
17381afb1eeSMike Rapoport (Microsoft) 
17481afb1eeSMike Rapoport (Microsoft) 	for (i = 0; i < NR_ORDERS; i++) {
17581afb1eeSMike Rapoport (Microsoft) 		if (!((1 << i) & shmem_orders)) {
17681afb1eeSMike Rapoport (Microsoft) 			settings->shmem_hugepages[i].enabled = SHMEM_NEVER;
17781afb1eeSMike Rapoport (Microsoft) 			continue;
17881afb1eeSMike Rapoport (Microsoft) 		}
17981afb1eeSMike Rapoport (Microsoft) 		snprintf(path, PATH_MAX, "hugepages-%ukB/shmem_enabled",
18081afb1eeSMike Rapoport (Microsoft) 			(getpagesize() >> 10) << i);
18181afb1eeSMike Rapoport (Microsoft) 		settings->shmem_hugepages[i].enabled =
18281afb1eeSMike Rapoport (Microsoft) 			thp_read_string(path, shmem_enabled_strings);
18381afb1eeSMike Rapoport (Microsoft) 	}
18481afb1eeSMike Rapoport (Microsoft) }
18581afb1eeSMike Rapoport (Microsoft) 
18681afb1eeSMike Rapoport (Microsoft) void thp_write_settings(struct thp_settings *settings)
18781afb1eeSMike Rapoport (Microsoft) {
18881afb1eeSMike Rapoport (Microsoft) 	struct khugepaged_settings *khugepaged = &settings->khugepaged;
18981afb1eeSMike Rapoport (Microsoft) 	unsigned long orders = thp_supported_orders();
19081afb1eeSMike Rapoport (Microsoft) 	unsigned long shmem_orders = thp_shmem_supported_orders();
19181afb1eeSMike Rapoport (Microsoft) 	char path[PATH_MAX];
19281afb1eeSMike Rapoport (Microsoft) 	int enabled;
19381afb1eeSMike Rapoport (Microsoft) 	int i;
19481afb1eeSMike Rapoport (Microsoft) 
19581afb1eeSMike Rapoport (Microsoft) 	thp_write_string("enabled", thp_enabled_strings[settings->thp_enabled]);
19681afb1eeSMike Rapoport (Microsoft) 	thp_write_string("defrag", thp_defrag_strings[settings->thp_defrag]);
19781afb1eeSMike Rapoport (Microsoft) 	thp_write_string("shmem_enabled",
19881afb1eeSMike Rapoport (Microsoft) 			shmem_enabled_strings[settings->shmem_enabled]);
19981afb1eeSMike Rapoport (Microsoft) 	thp_write_num("use_zero_page", settings->use_zero_page);
20081afb1eeSMike Rapoport (Microsoft) 
20181afb1eeSMike Rapoport (Microsoft) 	thp_write_num("khugepaged/defrag", khugepaged->defrag);
20281afb1eeSMike Rapoport (Microsoft) 	thp_write_num("khugepaged/alloc_sleep_millisecs",
20381afb1eeSMike Rapoport (Microsoft) 			khugepaged->alloc_sleep_millisecs);
20481afb1eeSMike Rapoport (Microsoft) 	thp_write_num("khugepaged/scan_sleep_millisecs",
20581afb1eeSMike Rapoport (Microsoft) 			khugepaged->scan_sleep_millisecs);
20681afb1eeSMike Rapoport (Microsoft) 	thp_write_num("khugepaged/max_ptes_none", khugepaged->max_ptes_none);
20781afb1eeSMike Rapoport (Microsoft) 	thp_write_num("khugepaged/max_ptes_swap", khugepaged->max_ptes_swap);
20881afb1eeSMike Rapoport (Microsoft) 	thp_write_num("khugepaged/max_ptes_shared", khugepaged->max_ptes_shared);
20981afb1eeSMike Rapoport (Microsoft) 	thp_write_num("khugepaged/pages_to_scan", khugepaged->pages_to_scan);
21081afb1eeSMike Rapoport (Microsoft) 
21181afb1eeSMike Rapoport (Microsoft) 	if (dev_queue_read_ahead_path[0])
21281afb1eeSMike Rapoport (Microsoft) 		write_num(dev_queue_read_ahead_path, settings->read_ahead_kb);
21381afb1eeSMike Rapoport (Microsoft) 
21481afb1eeSMike Rapoport (Microsoft) 	for (i = 0; i < NR_ORDERS; i++) {
21581afb1eeSMike Rapoport (Microsoft) 		if (!((1 << i) & orders))
21681afb1eeSMike Rapoport (Microsoft) 			continue;
21781afb1eeSMike Rapoport (Microsoft) 		snprintf(path, PATH_MAX, "hugepages-%ukB/enabled",
21881afb1eeSMike Rapoport (Microsoft) 			(getpagesize() >> 10) << i);
21981afb1eeSMike Rapoport (Microsoft) 		enabled = settings->hugepages[i].enabled;
22081afb1eeSMike Rapoport (Microsoft) 		thp_write_string(path, thp_enabled_strings[enabled]);
22181afb1eeSMike Rapoport (Microsoft) 	}
22281afb1eeSMike Rapoport (Microsoft) 
22381afb1eeSMike Rapoport (Microsoft) 	for (i = 0; i < NR_ORDERS; i++) {
22481afb1eeSMike Rapoport (Microsoft) 		if (!((1 << i) & shmem_orders))
22581afb1eeSMike Rapoport (Microsoft) 			continue;
22681afb1eeSMike Rapoport (Microsoft) 		snprintf(path, PATH_MAX, "hugepages-%ukB/shmem_enabled",
22781afb1eeSMike Rapoport (Microsoft) 			(getpagesize() >> 10) << i);
22881afb1eeSMike Rapoport (Microsoft) 		enabled = settings->shmem_hugepages[i].enabled;
22981afb1eeSMike Rapoport (Microsoft) 		thp_write_string(path, shmem_enabled_strings[enabled]);
23081afb1eeSMike Rapoport (Microsoft) 	}
23181afb1eeSMike Rapoport (Microsoft) }
23281afb1eeSMike Rapoport (Microsoft) 
23381afb1eeSMike Rapoport (Microsoft) struct thp_settings *thp_current_settings(void)
23481afb1eeSMike Rapoport (Microsoft) {
23581afb1eeSMike Rapoport (Microsoft) 	if (!settings_index) {
23681afb1eeSMike Rapoport (Microsoft) 		printf("Fail: No settings set");
23781afb1eeSMike Rapoport (Microsoft) 		exit(EXIT_FAILURE);
23881afb1eeSMike Rapoport (Microsoft) 	}
23981afb1eeSMike Rapoport (Microsoft) 	return settings_stack + settings_index - 1;
24081afb1eeSMike Rapoport (Microsoft) }
24181afb1eeSMike Rapoport (Microsoft) 
24281afb1eeSMike Rapoport (Microsoft) void thp_push_settings(struct thp_settings *settings)
24381afb1eeSMike Rapoport (Microsoft) {
24481afb1eeSMike Rapoport (Microsoft) 	if (settings_index >= MAX_SETTINGS_DEPTH) {
24581afb1eeSMike Rapoport (Microsoft) 		printf("Fail: Settings stack exceeded");
24681afb1eeSMike Rapoport (Microsoft) 		exit(EXIT_FAILURE);
24781afb1eeSMike Rapoport (Microsoft) 	}
24881afb1eeSMike Rapoport (Microsoft) 	settings_stack[settings_index++] = *settings;
24981afb1eeSMike Rapoport (Microsoft) 	thp_write_settings(thp_current_settings());
25081afb1eeSMike Rapoport (Microsoft) }
25181afb1eeSMike Rapoport (Microsoft) 
25281afb1eeSMike Rapoport (Microsoft) void thp_pop_settings(void)
25381afb1eeSMike Rapoport (Microsoft) {
25481afb1eeSMike Rapoport (Microsoft) 	if (settings_index <= 0) {
25581afb1eeSMike Rapoport (Microsoft) 		printf("Fail: Settings stack empty");
25681afb1eeSMike Rapoport (Microsoft) 		exit(EXIT_FAILURE);
25781afb1eeSMike Rapoport (Microsoft) 	}
25881afb1eeSMike Rapoport (Microsoft) 	--settings_index;
25981afb1eeSMike Rapoport (Microsoft) 	thp_write_settings(thp_current_settings());
26081afb1eeSMike Rapoport (Microsoft) }
26181afb1eeSMike Rapoport (Microsoft) 
26281afb1eeSMike Rapoport (Microsoft) void thp_restore_settings(void)
26381afb1eeSMike Rapoport (Microsoft) {
26481afb1eeSMike Rapoport (Microsoft) 	if (thp_settings_saved)
26581afb1eeSMike Rapoport (Microsoft) 		thp_write_settings(&saved_settings);
26681afb1eeSMike Rapoport (Microsoft) }
26781afb1eeSMike Rapoport (Microsoft) 
268*08e51ae5SMike Rapoport (Microsoft) static void __thp_save_settings(void)
26981afb1eeSMike Rapoport (Microsoft) {
270*08e51ae5SMike Rapoport (Microsoft) 	if (!thp_available())
271*08e51ae5SMike Rapoport (Microsoft) 		return;
27281afb1eeSMike Rapoport (Microsoft) 
273*08e51ae5SMike Rapoport (Microsoft) 	if (thp_settings_saved)
274*08e51ae5SMike Rapoport (Microsoft) 		return;
27581afb1eeSMike Rapoport (Microsoft) 
27681afb1eeSMike Rapoport (Microsoft) 	thp_read_settings(&saved_settings);
27781afb1eeSMike Rapoport (Microsoft) 	thp_settings_saved = true;
27881afb1eeSMike Rapoport (Microsoft) }
27981afb1eeSMike Rapoport (Microsoft) 
28081afb1eeSMike Rapoport (Microsoft) void thp_set_read_ahead_path(char *path)
28181afb1eeSMike Rapoport (Microsoft) {
28281afb1eeSMike Rapoport (Microsoft) 	if (!path) {
28381afb1eeSMike Rapoport (Microsoft) 		dev_queue_read_ahead_path[0] = '\0';
28481afb1eeSMike Rapoport (Microsoft) 		return;
28581afb1eeSMike Rapoport (Microsoft) 	}
28681afb1eeSMike Rapoport (Microsoft) 
28781afb1eeSMike Rapoport (Microsoft) 	strncpy(dev_queue_read_ahead_path, path,
28881afb1eeSMike Rapoport (Microsoft) 		sizeof(dev_queue_read_ahead_path));
28981afb1eeSMike Rapoport (Microsoft) 	dev_queue_read_ahead_path[sizeof(dev_queue_read_ahead_path) - 1] = '\0';
29081afb1eeSMike Rapoport (Microsoft) }
29181afb1eeSMike Rapoport (Microsoft) 
29281afb1eeSMike Rapoport (Microsoft) static unsigned long __thp_supported_orders(bool is_shmem)
29381afb1eeSMike Rapoport (Microsoft) {
29481afb1eeSMike Rapoport (Microsoft) 	unsigned long orders = 0;
29581afb1eeSMike Rapoport (Microsoft) 	char path[PATH_MAX];
29681afb1eeSMike Rapoport (Microsoft) 	char buf[256];
29781afb1eeSMike Rapoport (Microsoft) 	int ret, i;
29881afb1eeSMike Rapoport (Microsoft) 	char anon_dir[] = "enabled";
29981afb1eeSMike Rapoport (Microsoft) 	char shmem_dir[] = "shmem_enabled";
30081afb1eeSMike Rapoport (Microsoft) 
30181afb1eeSMike Rapoport (Microsoft) 	for (i = 0; i < NR_ORDERS; i++) {
30281afb1eeSMike Rapoport (Microsoft) 		ret = snprintf(path, PATH_MAX, THP_SYSFS "hugepages-%ukB/%s",
30381afb1eeSMike Rapoport (Microsoft) 			       (getpagesize() >> 10) << i, is_shmem ? shmem_dir : anon_dir);
30481afb1eeSMike Rapoport (Microsoft) 		if (ret >= PATH_MAX) {
30581afb1eeSMike Rapoport (Microsoft) 			printf("%s: Pathname is too long\n", __func__);
30681afb1eeSMike Rapoport (Microsoft) 			exit(EXIT_FAILURE);
30781afb1eeSMike Rapoport (Microsoft) 		}
30881afb1eeSMike Rapoport (Microsoft) 
30981afb1eeSMike Rapoport (Microsoft) 		ret = read_file(path, buf, sizeof(buf));
31081afb1eeSMike Rapoport (Microsoft) 		if (ret)
31181afb1eeSMike Rapoport (Microsoft) 			orders |= 1UL << i;
31281afb1eeSMike Rapoport (Microsoft) 	}
31381afb1eeSMike Rapoport (Microsoft) 
31481afb1eeSMike Rapoport (Microsoft) 	return orders;
31581afb1eeSMike Rapoport (Microsoft) }
31681afb1eeSMike Rapoport (Microsoft) 
31781afb1eeSMike Rapoport (Microsoft) unsigned long thp_supported_orders(void)
31881afb1eeSMike Rapoport (Microsoft) {
31981afb1eeSMike Rapoport (Microsoft) 	return __thp_supported_orders(false);
32081afb1eeSMike Rapoport (Microsoft) }
32181afb1eeSMike Rapoport (Microsoft) 
32281afb1eeSMike Rapoport (Microsoft) unsigned long thp_shmem_supported_orders(void)
32381afb1eeSMike Rapoport (Microsoft) {
32481afb1eeSMike Rapoport (Microsoft) 	return __thp_supported_orders(true);
32581afb1eeSMike Rapoport (Microsoft) }
32681afb1eeSMike Rapoport (Microsoft) 
32781afb1eeSMike Rapoport (Microsoft) bool thp_available(void)
32881afb1eeSMike Rapoport (Microsoft) {
32981afb1eeSMike Rapoport (Microsoft) 	if (access(THP_SYSFS, F_OK) != 0)
33081afb1eeSMike Rapoport (Microsoft) 		return false;
33181afb1eeSMike Rapoport (Microsoft) 	return true;
33281afb1eeSMike Rapoport (Microsoft) }
33381afb1eeSMike Rapoport (Microsoft) 
33481afb1eeSMike Rapoport (Microsoft) bool thp_is_enabled(void)
33581afb1eeSMike Rapoport (Microsoft) {
33681afb1eeSMike Rapoport (Microsoft) 	if (!thp_available())
33781afb1eeSMike Rapoport (Microsoft) 		return false;
33881afb1eeSMike Rapoport (Microsoft) 
33981afb1eeSMike Rapoport (Microsoft) 	int mode = thp_read_string("enabled", thp_enabled_strings);
34081afb1eeSMike Rapoport (Microsoft) 
34181afb1eeSMike Rapoport (Microsoft) 	/* THP is considered enabled if it's either "always" or "madvise" */
34281afb1eeSMike Rapoport (Microsoft) 	return mode == 1 || mode == 3;
34381afb1eeSMike Rapoport (Microsoft) }
3441bdc1698SMike Rapoport (Microsoft) 
345*08e51ae5SMike Rapoport (Microsoft) #define HUGETLB_MAX_NR_PAGESIZES 10
346*08e51ae5SMike Rapoport (Microsoft) struct hugetlb_settings {
347*08e51ae5SMike Rapoport (Microsoft) 	unsigned long nr_hugepages[HUGETLB_MAX_NR_PAGESIZES];
348*08e51ae5SMike Rapoport (Microsoft) 	unsigned long sizes[HUGETLB_MAX_NR_PAGESIZES];
349*08e51ae5SMike Rapoport (Microsoft) 	unsigned long default_size;
350*08e51ae5SMike Rapoport (Microsoft) 	int nr_sizes;
351*08e51ae5SMike Rapoport (Microsoft) };
352*08e51ae5SMike Rapoport (Microsoft) 
353*08e51ae5SMike Rapoport (Microsoft) static struct hugetlb_settings hugetlb_saved_settings;
354*08e51ae5SMike Rapoport (Microsoft) static bool hugetlb_settings_saved;
355*08e51ae5SMike Rapoport (Microsoft) 
3560020a1f5SMike Rapoport (Microsoft) int detect_hugetlb_page_sizes(unsigned long sizes[], int max)
3571bdc1698SMike Rapoport (Microsoft) {
358*08e51ae5SMike Rapoport (Microsoft) 	static struct hugetlb_settings *settings = &hugetlb_saved_settings;
359*08e51ae5SMike Rapoport (Microsoft) 	DIR *dir;
3601bdc1698SMike Rapoport (Microsoft) 	int count = 0;
3611bdc1698SMike Rapoport (Microsoft) 
362*08e51ae5SMike Rapoport (Microsoft) 	if (settings->nr_sizes) {
363*08e51ae5SMike Rapoport (Microsoft) 		if (settings->nr_sizes < max)
364*08e51ae5SMike Rapoport (Microsoft) 			max = settings->nr_sizes;
365*08e51ae5SMike Rapoport (Microsoft) 		for (count = 0; count < max; count++)
366*08e51ae5SMike Rapoport (Microsoft) 			sizes[count] = settings->sizes[count];
367*08e51ae5SMike Rapoport (Microsoft) 		return count;
368*08e51ae5SMike Rapoport (Microsoft) 	}
369*08e51ae5SMike Rapoport (Microsoft) 
370*08e51ae5SMike Rapoport (Microsoft) 	dir = opendir("/sys/kernel/mm/hugepages/");
3711bdc1698SMike Rapoport (Microsoft) 	if (!dir)
3721bdc1698SMike Rapoport (Microsoft) 		return 0;
3731bdc1698SMike Rapoport (Microsoft) 
3741bdc1698SMike Rapoport (Microsoft) 	while (count < max) {
3751bdc1698SMike Rapoport (Microsoft) 		struct dirent *entry = readdir(dir);
3761bdc1698SMike Rapoport (Microsoft) 		size_t kb;
3771bdc1698SMike Rapoport (Microsoft) 
3781bdc1698SMike Rapoport (Microsoft) 		if (!entry)
3791bdc1698SMike Rapoport (Microsoft) 			break;
3801bdc1698SMike Rapoport (Microsoft) 		if (entry->d_type != DT_DIR)
3811bdc1698SMike Rapoport (Microsoft) 			continue;
3821bdc1698SMike Rapoport (Microsoft) 		if (sscanf(entry->d_name, "hugepages-%zukB", &kb) != 1)
3831bdc1698SMike Rapoport (Microsoft) 			continue;
3841bdc1698SMike Rapoport (Microsoft) 		sizes[count++] = kb * 1024;
3851bdc1698SMike Rapoport (Microsoft) 		ksft_print_msg("[INFO] detected hugetlb page size: %zu KiB\n",
3861bdc1698SMike Rapoport (Microsoft) 			       kb);
3871bdc1698SMike Rapoport (Microsoft) 	}
3881bdc1698SMike Rapoport (Microsoft) 	closedir(dir);
3891bdc1698SMike Rapoport (Microsoft) 	return count;
3901bdc1698SMike Rapoport (Microsoft) }
3911bdc1698SMike Rapoport (Microsoft) 
3921bdc1698SMike Rapoport (Microsoft) unsigned long default_huge_page_size(void)
3931bdc1698SMike Rapoport (Microsoft) {
394*08e51ae5SMike Rapoport (Microsoft) 	static struct hugetlb_settings *settings = &hugetlb_saved_settings;
3951bdc1698SMike Rapoport (Microsoft) 	unsigned long hps = 0;
3961bdc1698SMike Rapoport (Microsoft) 	char *line = NULL;
3971bdc1698SMike Rapoport (Microsoft) 	size_t linelen = 0;
398*08e51ae5SMike Rapoport (Microsoft) 	FILE *f;
3991bdc1698SMike Rapoport (Microsoft) 
400*08e51ae5SMike Rapoport (Microsoft) 	if (settings->default_size)
401*08e51ae5SMike Rapoport (Microsoft) 		return settings->default_size;
402*08e51ae5SMike Rapoport (Microsoft) 
403*08e51ae5SMike Rapoport (Microsoft) 	f = fopen("/proc/meminfo", "r");
4041bdc1698SMike Rapoport (Microsoft) 	if (!f)
4051bdc1698SMike Rapoport (Microsoft) 		return 0;
4061bdc1698SMike Rapoport (Microsoft) 	while (getline(&line, &linelen, f) > 0) {
4071bdc1698SMike Rapoport (Microsoft) 		if (sscanf(line, "Hugepagesize:       %lu kB", &hps) == 1) {
4081bdc1698SMike Rapoport (Microsoft) 			hps <<= 10;
4091bdc1698SMike Rapoport (Microsoft) 			break;
4101bdc1698SMike Rapoport (Microsoft) 		}
4111bdc1698SMike Rapoport (Microsoft) 	}
4121bdc1698SMike Rapoport (Microsoft) 
4131bdc1698SMike Rapoport (Microsoft) 	free(line);
4141bdc1698SMike Rapoport (Microsoft) 	fclose(f);
4151bdc1698SMike Rapoport (Microsoft) 	return hps;
4161bdc1698SMike Rapoport (Microsoft) }
4171bdc1698SMike Rapoport (Microsoft) 
41827477b28SMike Rapoport (Microsoft) static void hugetlb_sysfs_path(char *buf, size_t buflen,
41927477b28SMike Rapoport (Microsoft) 			       unsigned long size, const char *attr)
42027477b28SMike Rapoport (Microsoft) {
42127477b28SMike Rapoport (Microsoft) 	snprintf(buf, buflen, "/sys/kernel/mm/hugepages/hugepages-%lukB/%s",
42227477b28SMike Rapoport (Microsoft) 		 size / 1024, attr);
42327477b28SMike Rapoport (Microsoft) }
42427477b28SMike Rapoport (Microsoft) 
42527477b28SMike Rapoport (Microsoft) unsigned long hugetlb_nr_pages(unsigned long size)
42627477b28SMike Rapoport (Microsoft) {
42727477b28SMike Rapoport (Microsoft) 	char path[PATH_MAX];
42827477b28SMike Rapoport (Microsoft) 
42927477b28SMike Rapoport (Microsoft) 	hugetlb_sysfs_path(path, sizeof(path), size, "nr_hugepages");
43027477b28SMike Rapoport (Microsoft) 
43127477b28SMike Rapoport (Microsoft) 	return read_num(path);
43227477b28SMike Rapoport (Microsoft) }
43327477b28SMike Rapoport (Microsoft) 
43427477b28SMike Rapoport (Microsoft) void hugetlb_set_nr_pages(unsigned long size, unsigned long nr)
43527477b28SMike Rapoport (Microsoft) {
43627477b28SMike Rapoport (Microsoft) 	char path[PATH_MAX];
43727477b28SMike Rapoport (Microsoft) 
43827477b28SMike Rapoport (Microsoft) 	hugetlb_sysfs_path(path, sizeof(path), size, "nr_hugepages");
43927477b28SMike Rapoport (Microsoft) 
44027477b28SMike Rapoport (Microsoft) 	write_num(path, nr);
44127477b28SMike Rapoport (Microsoft) }
442024ec9a7SMike Rapoport (Microsoft) 
443024ec9a7SMike Rapoport (Microsoft) unsigned long hugetlb_free_pages(unsigned long size)
444024ec9a7SMike Rapoport (Microsoft) {
445024ec9a7SMike Rapoport (Microsoft) 	char path[PATH_MAX];
446024ec9a7SMike Rapoport (Microsoft) 
447024ec9a7SMike Rapoport (Microsoft) 	hugetlb_sysfs_path(path, sizeof(path), size, "free_hugepages");
448024ec9a7SMike Rapoport (Microsoft) 
449024ec9a7SMike Rapoport (Microsoft) 	return read_num(path);
450024ec9a7SMike Rapoport (Microsoft) }
451*08e51ae5SMike Rapoport (Microsoft) 
452*08e51ae5SMike Rapoport (Microsoft) static bool __hugetlb_setup(unsigned long size, unsigned long nr)
453*08e51ae5SMike Rapoport (Microsoft) {
454*08e51ae5SMike Rapoport (Microsoft) 	unsigned long free = hugetlb_free_pages(size);
455*08e51ae5SMike Rapoport (Microsoft) 	unsigned long total = hugetlb_nr_pages(size);
456*08e51ae5SMike Rapoport (Microsoft) 
457*08e51ae5SMike Rapoport (Microsoft) 	if (free >= nr)
458*08e51ae5SMike Rapoport (Microsoft) 		return true;
459*08e51ae5SMike Rapoport (Microsoft) 
460*08e51ae5SMike Rapoport (Microsoft) 	hugetlb_set_nr_pages(size, total + (nr - free));
461*08e51ae5SMike Rapoport (Microsoft) 
462*08e51ae5SMike Rapoport (Microsoft) 	return hugetlb_free_pages(size) >= nr;
463*08e51ae5SMike Rapoport (Microsoft) }
464*08e51ae5SMike Rapoport (Microsoft) 
465*08e51ae5SMike Rapoport (Microsoft) bool hugetlb_setup_default(unsigned long nr)
466*08e51ae5SMike Rapoport (Microsoft) {
467*08e51ae5SMike Rapoport (Microsoft) 	unsigned long size;
468*08e51ae5SMike Rapoport (Microsoft) 
469*08e51ae5SMike Rapoport (Microsoft) 	hugetlb_save_settings();
470*08e51ae5SMike Rapoport (Microsoft) 	size = default_huge_page_size();
471*08e51ae5SMike Rapoport (Microsoft) 	if (!size)
472*08e51ae5SMike Rapoport (Microsoft) 		return false;
473*08e51ae5SMike Rapoport (Microsoft) 
474*08e51ae5SMike Rapoport (Microsoft) 	return __hugetlb_setup(size, nr);
475*08e51ae5SMike Rapoport (Microsoft) }
476*08e51ae5SMike Rapoport (Microsoft) 
477*08e51ae5SMike Rapoport (Microsoft) bool hugetlb_setup_default_exact(unsigned long nr)
478*08e51ae5SMike Rapoport (Microsoft) {
479*08e51ae5SMike Rapoport (Microsoft) 	unsigned long size;
480*08e51ae5SMike Rapoport (Microsoft) 
481*08e51ae5SMike Rapoport (Microsoft) 	hugetlb_save_settings();
482*08e51ae5SMike Rapoport (Microsoft) 	size = default_huge_page_size();
483*08e51ae5SMike Rapoport (Microsoft) 	if (!size)
484*08e51ae5SMike Rapoport (Microsoft) 		return false;
485*08e51ae5SMike Rapoport (Microsoft) 
486*08e51ae5SMike Rapoport (Microsoft) 	hugetlb_set_nr_pages(size, nr);
487*08e51ae5SMike Rapoport (Microsoft) 
488*08e51ae5SMike Rapoport (Microsoft) 	return hugetlb_free_pages(size) == nr;
489*08e51ae5SMike Rapoport (Microsoft) }
490*08e51ae5SMike Rapoport (Microsoft) 
491*08e51ae5SMike Rapoport (Microsoft) unsigned long hugetlb_setup(unsigned long nr, unsigned long sizes[],
492*08e51ae5SMike Rapoport (Microsoft) 			    int max)
493*08e51ae5SMike Rapoport (Microsoft) {
494*08e51ae5SMike Rapoport (Microsoft) 	unsigned long enabled[10];
495*08e51ae5SMike Rapoport (Microsoft) 	int nr_sizes = 0;
496*08e51ae5SMike Rapoport (Microsoft) 	int nr_enabled;
497*08e51ae5SMike Rapoport (Microsoft) 
498*08e51ae5SMike Rapoport (Microsoft) 	hugetlb_save_settings();
499*08e51ae5SMike Rapoport (Microsoft) 
500*08e51ae5SMike Rapoport (Microsoft) 	nr_enabled = detect_hugetlb_page_sizes(enabled, ARRAY_SIZE(enabled));
501*08e51ae5SMike Rapoport (Microsoft) 	if (!nr_enabled)
502*08e51ae5SMike Rapoport (Microsoft) 		return 0;
503*08e51ae5SMike Rapoport (Microsoft) 
504*08e51ae5SMike Rapoport (Microsoft) 	if (nr_enabled > max) {
505*08e51ae5SMike Rapoport (Microsoft) 		ksft_print_msg("detected %d huge page sizes, will only test %d\n", nr_enabled, max);
506*08e51ae5SMike Rapoport (Microsoft) 		nr_enabled = max;
507*08e51ae5SMike Rapoport (Microsoft) 	}
508*08e51ae5SMike Rapoport (Microsoft) 
509*08e51ae5SMike Rapoport (Microsoft) 	/* request nr HugeTLB pages of every size. */
510*08e51ae5SMike Rapoport (Microsoft) 	for (int i = 0; i < nr_enabled; i++) {
511*08e51ae5SMike Rapoport (Microsoft) 		if (!__hugetlb_setup(enabled[i], nr))
512*08e51ae5SMike Rapoport (Microsoft) 			continue;
513*08e51ae5SMike Rapoport (Microsoft) 		sizes[nr_sizes++] = enabled[i];
514*08e51ae5SMike Rapoport (Microsoft) 	}
515*08e51ae5SMike Rapoport (Microsoft) 
516*08e51ae5SMike Rapoport (Microsoft) 	return nr_sizes;
517*08e51ae5SMike Rapoport (Microsoft) }
518*08e51ae5SMike Rapoport (Microsoft) 
519*08e51ae5SMike Rapoport (Microsoft) static void __hugetlb_save_settings(void)
520*08e51ae5SMike Rapoport (Microsoft) {
521*08e51ae5SMike Rapoport (Microsoft) 	struct hugetlb_settings *settings = &hugetlb_saved_settings;
522*08e51ae5SMike Rapoport (Microsoft) 	int nr_sizes;
523*08e51ae5SMike Rapoport (Microsoft) 
524*08e51ae5SMike Rapoport (Microsoft) 	if (hugetlb_settings_saved)
525*08e51ae5SMike Rapoport (Microsoft) 		return;
526*08e51ae5SMike Rapoport (Microsoft) 
527*08e51ae5SMike Rapoport (Microsoft) 	settings->default_size = default_huge_page_size();
528*08e51ae5SMike Rapoport (Microsoft) 	if (!settings->default_size)
529*08e51ae5SMike Rapoport (Microsoft) 		return;
530*08e51ae5SMike Rapoport (Microsoft) 
531*08e51ae5SMike Rapoport (Microsoft) 	nr_sizes = detect_hugetlb_page_sizes(settings->sizes,
532*08e51ae5SMike Rapoport (Microsoft) 					     HUGETLB_MAX_NR_PAGESIZES);
533*08e51ae5SMike Rapoport (Microsoft) 	if (!nr_sizes) {
534*08e51ae5SMike Rapoport (Microsoft) 		settings->default_size = 0;
535*08e51ae5SMike Rapoport (Microsoft) 		return;
536*08e51ae5SMike Rapoport (Microsoft) 	}
537*08e51ae5SMike Rapoport (Microsoft) 
538*08e51ae5SMike Rapoport (Microsoft) 	for (int i = 0; i < nr_sizes; i++) {
539*08e51ae5SMike Rapoport (Microsoft) 		unsigned long sz = settings->sizes[i];
540*08e51ae5SMike Rapoport (Microsoft) 
541*08e51ae5SMike Rapoport (Microsoft) 		if (!sz)
542*08e51ae5SMike Rapoport (Microsoft) 			continue;
543*08e51ae5SMike Rapoport (Microsoft) 		settings->nr_hugepages[i] = hugetlb_nr_pages(sz);
544*08e51ae5SMike Rapoport (Microsoft) 	}
545*08e51ae5SMike Rapoport (Microsoft) 
546*08e51ae5SMike Rapoport (Microsoft) 	settings->nr_sizes = nr_sizes;
547*08e51ae5SMike Rapoport (Microsoft) 	hugetlb_settings_saved = true;
548*08e51ae5SMike Rapoport (Microsoft) }
549*08e51ae5SMike Rapoport (Microsoft) 
550*08e51ae5SMike Rapoport (Microsoft) void hugetlb_restore_settings(void)
551*08e51ae5SMike Rapoport (Microsoft) {
552*08e51ae5SMike Rapoport (Microsoft) 	struct hugetlb_settings *settings = &hugetlb_saved_settings;
553*08e51ae5SMike Rapoport (Microsoft) 
554*08e51ae5SMike Rapoport (Microsoft) 	if (!hugetlb_settings_saved || !settings->default_size)
555*08e51ae5SMike Rapoport (Microsoft) 		return;
556*08e51ae5SMike Rapoport (Microsoft) 
557*08e51ae5SMike Rapoport (Microsoft) 	for (int i = 0; i < HUGETLB_MAX_NR_PAGESIZES; i++) {
558*08e51ae5SMike Rapoport (Microsoft) 		unsigned long sz = settings->sizes[i];
559*08e51ae5SMike Rapoport (Microsoft) 
560*08e51ae5SMike Rapoport (Microsoft) 		if (!sz)
561*08e51ae5SMike Rapoport (Microsoft) 			continue;
562*08e51ae5SMike Rapoport (Microsoft) 
563*08e51ae5SMike Rapoport (Microsoft) 		hugetlb_set_nr_pages(sz, settings->nr_hugepages[i]);
564*08e51ae5SMike Rapoport (Microsoft) 	}
565*08e51ae5SMike Rapoport (Microsoft) }
566*08e51ae5SMike Rapoport (Microsoft) 
567*08e51ae5SMike Rapoport (Microsoft) static void hugepage_restore_settings_atexit(void)
568*08e51ae5SMike Rapoport (Microsoft) {
569*08e51ae5SMike Rapoport (Microsoft) 	if (thp_settings_saved)
570*08e51ae5SMike Rapoport (Microsoft) 		thp_restore_settings();
571*08e51ae5SMike Rapoport (Microsoft) 	if (hugetlb_settings_saved)
572*08e51ae5SMike Rapoport (Microsoft) 		hugetlb_restore_settings();
573*08e51ae5SMike Rapoport (Microsoft) }
574*08e51ae5SMike Rapoport (Microsoft) 
575*08e51ae5SMike Rapoport (Microsoft) static void hugepage_restore_settings_sighandler(int sig)
576*08e51ae5SMike Rapoport (Microsoft) {
577*08e51ae5SMike Rapoport (Microsoft) 	/* exit() will invoke the hugepage_restore_settings_atexit handler. */
578*08e51ae5SMike Rapoport (Microsoft) 	exit(KSFT_FAIL);
579*08e51ae5SMike Rapoport (Microsoft) }
580*08e51ae5SMike Rapoport (Microsoft) 
581*08e51ae5SMike Rapoport (Microsoft) void hugepage_save_settings(bool thp, bool hugetlb)
582*08e51ae5SMike Rapoport (Microsoft) {
583*08e51ae5SMike Rapoport (Microsoft) 	if (!thp && !hugetlb)
584*08e51ae5SMike Rapoport (Microsoft) 		return;
585*08e51ae5SMike Rapoport (Microsoft) 
586*08e51ae5SMike Rapoport (Microsoft) 	if (thp)
587*08e51ae5SMike Rapoport (Microsoft) 		__thp_save_settings();
588*08e51ae5SMike Rapoport (Microsoft) 	if (hugetlb)
589*08e51ae5SMike Rapoport (Microsoft) 		__hugetlb_save_settings();
590*08e51ae5SMike Rapoport (Microsoft) 
591*08e51ae5SMike Rapoport (Microsoft) 	/*
592*08e51ae5SMike Rapoport (Microsoft) 	 * setup exit hooks to make sure THP and HugeTLB settings are
593*08e51ae5SMike Rapoport (Microsoft) 	 * restored on graceful and error exits and signals
594*08e51ae5SMike Rapoport (Microsoft) 	 */
595*08e51ae5SMike Rapoport (Microsoft) 	atexit(hugepage_restore_settings_atexit);
596*08e51ae5SMike Rapoport (Microsoft) 	signal(SIGTERM, hugepage_restore_settings_sighandler);
597*08e51ae5SMike Rapoport (Microsoft) 	signal(SIGINT, hugepage_restore_settings_sighandler);
598*08e51ae5SMike Rapoport (Microsoft) 	signal(SIGHUP, hugepage_restore_settings_sighandler);
599*08e51ae5SMike Rapoport (Microsoft) 	signal(SIGQUIT, hugepage_restore_settings_sighandler);
600*08e51ae5SMike Rapoport (Microsoft) }
601