brintos

brintos / linux-shallow public Read only

0
0
Text · 4.3 KiB · 88c74bc Raw
167 lines · c
1// SPDX-License-Identifier: GPL-2.02// Copyright (C) 2020 ARM Limited3 4#define _GNU_SOURCE5 6#include <errno.h>7#include <fcntl.h>8#include <signal.h>9#include <stdio.h>10#include <stdlib.h>11#include <string.h>12#include <ucontext.h>13#include <sys/mman.h>14 15#include "kselftest.h"16#include "mte_common_util.h"17#include "mte_def.h"18 19#define TEST_UNIT	1020#define PATH_KSM	"/sys/kernel/mm/ksm/"21#define MAX_LOOP	422 23static size_t page_sz;24static unsigned long ksm_sysfs[5];25 26static unsigned long read_sysfs(char *str)27{28	FILE *f;29	unsigned long val = 0;30 31	f = fopen(str, "r");32	if (!f) {33		ksft_print_msg("ERR: missing %s\n", str);34		return 0;35	}36	if (fscanf(f, "%lu", &val) != 1) {37		ksft_print_msg("ERR: parsing %s\n", str);38		val = 0;39	}40	fclose(f);41	return val;42}43 44static void write_sysfs(char *str, unsigned long val)45{46	FILE *f;47 48	f = fopen(str, "w");49	if (!f) {50		ksft_print_msg("ERR: missing %s\n", str);51		return;52	}53	fprintf(f, "%lu", val);54	fclose(f);55}56 57static void mte_ksm_setup(void)58{59	ksm_sysfs[0] = read_sysfs(PATH_KSM "merge_across_nodes");60	write_sysfs(PATH_KSM "merge_across_nodes", 1);61	ksm_sysfs[1] = read_sysfs(PATH_KSM "sleep_millisecs");62	write_sysfs(PATH_KSM "sleep_millisecs", 0);63	ksm_sysfs[2] = read_sysfs(PATH_KSM "run");64	write_sysfs(PATH_KSM "run", 1);65	ksm_sysfs[3] = read_sysfs(PATH_KSM "max_page_sharing");66	write_sysfs(PATH_KSM "max_page_sharing", ksm_sysfs[3] + TEST_UNIT);67	ksm_sysfs[4] = read_sysfs(PATH_KSM "pages_to_scan");68	write_sysfs(PATH_KSM "pages_to_scan", ksm_sysfs[4] + TEST_UNIT);69}70 71static void mte_ksm_restore(void)72{73	write_sysfs(PATH_KSM "merge_across_nodes", ksm_sysfs[0]);74	write_sysfs(PATH_KSM "sleep_millisecs", ksm_sysfs[1]);75	write_sysfs(PATH_KSM "run", ksm_sysfs[2]);76	write_sysfs(PATH_KSM "max_page_sharing", ksm_sysfs[3]);77	write_sysfs(PATH_KSM "pages_to_scan", ksm_sysfs[4]);78}79 80static void mte_ksm_scan(void)81{82	int cur_count = read_sysfs(PATH_KSM "full_scans");83	int scan_count = cur_count + 1;84	int max_loop_count = MAX_LOOP;85 86	while ((cur_count < scan_count) && max_loop_count) {87		sleep(1);88		cur_count = read_sysfs(PATH_KSM "full_scans");89		max_loop_count--;90	}91#ifdef DEBUG92	ksft_print_msg("INFO: pages_shared=%lu pages_sharing=%lu\n",93			read_sysfs(PATH_KSM "pages_shared"),94			read_sysfs(PATH_KSM "pages_sharing"));95#endif96}97 98static int check_madvise_options(int mem_type, int mode, int mapping)99{100	char *ptr;101	int err, ret;102 103	err = KSFT_FAIL;104	if (access(PATH_KSM, F_OK) == -1) {105		ksft_print_msg("ERR: Kernel KSM config not enabled\n");106		return err;107	}108 109	mte_switch_mode(mode, MTE_ALLOW_NON_ZERO_TAG);110	ptr = mte_allocate_memory(TEST_UNIT * page_sz, mem_type, mapping, true);111	if (check_allocated_memory(ptr, TEST_UNIT * page_sz, mem_type, false) != KSFT_PASS)112		return KSFT_FAIL;113 114	/* Insert same data in all the pages */115	memset(ptr, 'A', TEST_UNIT * page_sz);116	ret = madvise(ptr, TEST_UNIT * page_sz, MADV_MERGEABLE);117	if (ret) {118		ksft_print_msg("ERR: madvise failed to set MADV_UNMERGEABLE\n");119		goto madvise_err;120	}121	mte_ksm_scan();122	/* Tagged pages should not merge */123	if ((read_sysfs(PATH_KSM "pages_shared") < 1) ||124	    (read_sysfs(PATH_KSM "pages_sharing") < (TEST_UNIT - 1)))125		err = KSFT_PASS;126madvise_err:127	mte_free_memory(ptr, TEST_UNIT * page_sz, mem_type, true);128	return err;129}130 131int main(int argc, char *argv[])132{133	int err;134 135	err = mte_default_setup();136	if (err)137		return err;138	page_sz = getpagesize();139	if (!page_sz) {140		ksft_print_msg("ERR: Unable to get page size\n");141		return KSFT_FAIL;142	}143	/* Register signal handlers */144	mte_register_signal(SIGBUS, mte_default_handler);145	mte_register_signal(SIGSEGV, mte_default_handler);146 147	/* Set test plan */148	ksft_set_plan(4);149 150	/* Enable KSM */151	mte_ksm_setup();152 153	evaluate_test(check_madvise_options(USE_MMAP, MTE_SYNC_ERR, MAP_PRIVATE),154		"Check KSM mte page merge for private mapping, sync mode and mmap memory\n");155	evaluate_test(check_madvise_options(USE_MMAP, MTE_ASYNC_ERR, MAP_PRIVATE),156		"Check KSM mte page merge for private mapping, async mode and mmap memory\n");157	evaluate_test(check_madvise_options(USE_MMAP, MTE_SYNC_ERR, MAP_SHARED),158		"Check KSM mte page merge for shared mapping, sync mode and mmap memory\n");159	evaluate_test(check_madvise_options(USE_MMAP, MTE_ASYNC_ERR, MAP_SHARED),160		"Check KSM mte page merge for shared mapping, async mode and mmap memory\n");161 162	mte_ksm_restore();163	mte_restore_setup();164	ksft_print_cnts();165	return ksft_get_fail_cnt() == 0 ? KSFT_PASS : KSFT_FAIL;166}167