cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

check_ksm_options.c (4439B)


      1// SPDX-License-Identifier: GPL-2.0
      2// Copyright (C) 2020 ARM Limited
      3
      4#define _GNU_SOURCE
      5
      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	10
     20#define PATH_KSM	"/sys/kernel/mm/ksm/"
     21#define MAX_LOOP	4
     22
     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 DEBUG
     92	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#endif
     96}
     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}