Path: blob/master/tools/testing/selftests/arm64/mte/check_ksm_options.c
26296 views
// SPDX-License-Identifier: GPL-2.01// Copyright (C) 2020 ARM Limited23#define _GNU_SOURCE45#include <errno.h>6#include <fcntl.h>7#include <signal.h>8#include <stdio.h>9#include <stdlib.h>10#include <string.h>11#include <ucontext.h>12#include <sys/mman.h>1314#include "kselftest.h"15#include "mte_common_util.h"16#include "mte_def.h"1718#define TEST_UNIT 1019#define PATH_KSM "/sys/kernel/mm/ksm/"20#define MAX_LOOP 42122static size_t page_sz;23static unsigned long ksm_sysfs[5];2425static unsigned long read_sysfs(char *str)26{27FILE *f;28unsigned long val = 0;2930f = fopen(str, "r");31if (!f) {32ksft_print_msg("ERR: missing %s\n", str);33return 0;34}35if (fscanf(f, "%lu", &val) != 1) {36ksft_print_msg("ERR: parsing %s\n", str);37val = 0;38}39fclose(f);40return val;41}4243static void write_sysfs(char *str, unsigned long val)44{45FILE *f;4647f = fopen(str, "w");48if (!f) {49ksft_print_msg("ERR: missing %s\n", str);50return;51}52fprintf(f, "%lu", val);53fclose(f);54}5556static void mte_ksm_setup(void)57{58ksm_sysfs[0] = read_sysfs(PATH_KSM "merge_across_nodes");59write_sysfs(PATH_KSM "merge_across_nodes", 1);60ksm_sysfs[1] = read_sysfs(PATH_KSM "sleep_millisecs");61write_sysfs(PATH_KSM "sleep_millisecs", 0);62ksm_sysfs[2] = read_sysfs(PATH_KSM "run");63write_sysfs(PATH_KSM "run", 1);64ksm_sysfs[3] = read_sysfs(PATH_KSM "max_page_sharing");65write_sysfs(PATH_KSM "max_page_sharing", ksm_sysfs[3] + TEST_UNIT);66ksm_sysfs[4] = read_sysfs(PATH_KSM "pages_to_scan");67write_sysfs(PATH_KSM "pages_to_scan", ksm_sysfs[4] + TEST_UNIT);68}6970static void mte_ksm_restore(void)71{72write_sysfs(PATH_KSM "merge_across_nodes", ksm_sysfs[0]);73write_sysfs(PATH_KSM "sleep_millisecs", ksm_sysfs[1]);74write_sysfs(PATH_KSM "run", ksm_sysfs[2]);75write_sysfs(PATH_KSM "max_page_sharing", ksm_sysfs[3]);76write_sysfs(PATH_KSM "pages_to_scan", ksm_sysfs[4]);77}7879static void mte_ksm_scan(void)80{81int cur_count = read_sysfs(PATH_KSM "full_scans");82int scan_count = cur_count + 1;83int max_loop_count = MAX_LOOP;8485while ((cur_count < scan_count) && max_loop_count) {86sleep(1);87cur_count = read_sysfs(PATH_KSM "full_scans");88max_loop_count--;89}90#ifdef DEBUG91ksft_print_msg("INFO: pages_shared=%lu pages_sharing=%lu\n",92read_sysfs(PATH_KSM "pages_shared"),93read_sysfs(PATH_KSM "pages_sharing"));94#endif95}9697static int check_madvise_options(int mem_type, int mode, int mapping)98{99char *ptr;100int err, ret;101102err = KSFT_FAIL;103if (access(PATH_KSM, F_OK) == -1) {104ksft_print_msg("ERR: Kernel KSM config not enabled\n");105return err;106}107108mte_switch_mode(mode, MTE_ALLOW_NON_ZERO_TAG, false);109ptr = mte_allocate_memory(TEST_UNIT * page_sz, mem_type, mapping, true);110if (check_allocated_memory(ptr, TEST_UNIT * page_sz, mem_type, false) != KSFT_PASS)111return KSFT_FAIL;112113/* Insert same data in all the pages */114memset(ptr, 'A', TEST_UNIT * page_sz);115ret = madvise(ptr, TEST_UNIT * page_sz, MADV_MERGEABLE);116if (ret) {117ksft_print_msg("ERR: madvise failed to set MADV_UNMERGEABLE\n");118goto madvise_err;119}120mte_ksm_scan();121/* Tagged pages should not merge */122if ((read_sysfs(PATH_KSM "pages_shared") < 1) ||123(read_sysfs(PATH_KSM "pages_sharing") < (TEST_UNIT - 1)))124err = KSFT_PASS;125madvise_err:126mte_free_memory(ptr, TEST_UNIT * page_sz, mem_type, true);127return err;128}129130int main(int argc, char *argv[])131{132int err;133134err = mte_default_setup();135if (err)136return err;137page_sz = getpagesize();138if (!page_sz) {139ksft_print_msg("ERR: Unable to get page size\n");140return KSFT_FAIL;141}142/* Register signal handlers */143mte_register_signal(SIGBUS, mte_default_handler, false);144mte_register_signal(SIGSEGV, mte_default_handler, false);145146/* Set test plan */147ksft_set_plan(4);148149/* Enable KSM */150mte_ksm_setup();151152evaluate_test(check_madvise_options(USE_MMAP, MTE_SYNC_ERR, MAP_PRIVATE),153"Check KSM mte page merge for private mapping, sync mode and mmap memory\n");154evaluate_test(check_madvise_options(USE_MMAP, MTE_ASYNC_ERR, MAP_PRIVATE),155"Check KSM mte page merge for private mapping, async mode and mmap memory\n");156evaluate_test(check_madvise_options(USE_MMAP, MTE_SYNC_ERR, MAP_SHARED),157"Check KSM mte page merge for shared mapping, sync mode and mmap memory\n");158evaluate_test(check_madvise_options(USE_MMAP, MTE_ASYNC_ERR, MAP_SHARED),159"Check KSM mte page merge for shared mapping, async mode and mmap memory\n");160161mte_ksm_restore();162mte_restore_setup();163ksft_print_cnts();164return ksft_get_fail_cnt() == 0 ? KSFT_PASS : KSFT_FAIL;165}166167168