~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/testing/selftests/arm64/mte/check_ksm_options.c

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 
 23 static size_t page_sz;
 24 static unsigned long ksm_sysfs[5];
 25 
 26 static 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 
 44 static 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 
 57 static 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 
 71 static 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 
 80 static 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 
 98 static 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;
126 madvise_err:
127         mte_free_memory(ptr, TEST_UNIT * page_sz, mem_type, true);
128         return err;
129 }
130 
131 int 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 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php