1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3# Please run as root
4
5# Kselftest framework requirement - SKIP code is 4.
6ksft_skip=4
7
8exitcode=0
9
10usage() {
11	cat <<EOF
12usage: ${BASH_SOURCE[0]:-$0} [ -h | -t "<categories>"]
13  -t: specify specific categories to tests to run
14  -h: display this message
15
16The default behavior is to run all tests.
17
18Alternatively, specific groups tests can be run by passing a string
19to the -t argument containing one or more of the following categories
20separated by spaces:
21- mmap
22	tests for mmap(2)
23- gup_test
24	tests for gup using gup_test interface
25- userfaultfd
26	tests for  userfaultfd(2)
27- compaction
28	a test for the patch "Allow compaction of unevictable pages"
29- mlock
30	tests for mlock(2)
31- mremap
32	tests for mremap(2)
33- hugevm
34	tests for very large virtual address space
35- vmalloc
36	vmalloc smoke tests
37- hmm
38	hmm smoke tests
39- madv_populate
40	test memadvise(2) MADV_POPULATE_{READ,WRITE} options
41- memfd_secret
42	test memfd_secret(2)
43- process_mrelease
44	test process_mrelease(2)
45- ksm
46	ksm tests that do not require >=2 NUMA nodes
47- ksm_numa
48	ksm tests that require >=2 NUMA nodes
49- pkey
50	memory protection key tests
51- soft_dirty
52	test soft dirty page bit semantics
53- cow
54	test copy-on-write semantics
55example: ./run_vmtests.sh -t "hmm mmap ksm"
56EOF
57	exit 0
58}
59
60
61while getopts "ht:" OPT; do
62	case ${OPT} in
63		"h") usage ;;
64		"t") VM_SELFTEST_ITEMS=${OPTARG} ;;
65	esac
66done
67shift $((OPTIND -1))
68
69# default behavior: run all tests
70VM_SELFTEST_ITEMS=${VM_SELFTEST_ITEMS:-default}
71
72test_selected() {
73	if [ "$VM_SELFTEST_ITEMS" == "default" ]; then
74		# If no VM_SELFTEST_ITEMS are specified, run all tests
75		return 0
76	fi
77	# If test selected argument is one of the test items
78	if [[ " ${VM_SELFTEST_ITEMS[*]} " =~ " ${1} " ]]; then
79	        return 0
80	else
81	        return 1
82	fi
83}
84
85# get huge pagesize and freepages from /proc/meminfo
86while read -r name size unit; do
87	if [ "$name" = "HugePages_Free:" ]; then
88		freepgs="$size"
89	fi
90	if [ "$name" = "Hugepagesize:" ]; then
91		hpgsize_KB="$size"
92	fi
93done < /proc/meminfo
94
95# Simple hugetlbfs tests have a hardcoded minimum requirement of
96# huge pages totaling 256MB (262144KB) in size.  The userfaultfd
97# hugetlb test requires a minimum of 2 * nr_cpus huge pages.  Take
98# both of these requirements into account and attempt to increase
99# number of huge pages available.
100nr_cpus=$(nproc)
101hpgsize_MB=$((hpgsize_KB / 1024))
102half_ufd_size_MB=$((((nr_cpus * hpgsize_MB + 127) / 128) * 128))
103needmem_KB=$((half_ufd_size_MB * 2 * 1024))
104
105# set proper nr_hugepages
106if [ -n "$freepgs" ] && [ -n "$hpgsize_KB" ]; then
107	nr_hugepgs=$(cat /proc/sys/vm/nr_hugepages)
108	needpgs=$((needmem_KB / hpgsize_KB))
109	tries=2
110	while [ "$tries" -gt 0 ] && [ "$freepgs" -lt "$needpgs" ]; do
111		lackpgs=$((needpgs - freepgs))
112		echo 3 > /proc/sys/vm/drop_caches
113		if ! echo $((lackpgs + nr_hugepgs)) > /proc/sys/vm/nr_hugepages; then
114			echo "Please run this test as root"
115			exit $ksft_skip
116		fi
117		while read -r name size unit; do
118			if [ "$name" = "HugePages_Free:" ]; then
119				freepgs=$size
120			fi
121		done < /proc/meminfo
122		tries=$((tries - 1))
123	done
124	if [ "$freepgs" -lt "$needpgs" ]; then
125		printf "Not enough huge pages available (%d < %d)\n" \
126		       "$freepgs" "$needpgs"
127		exit 1
128	fi
129else
130	echo "no hugetlbfs support in kernel?"
131	exit 1
132fi
133
134# filter 64bit architectures
135ARCH64STR="arm64 ia64 mips64 parisc64 ppc64 ppc64le riscv64 s390x sh64 sparc64 x86_64"
136if [ -z "$ARCH" ]; then
137	ARCH=$(uname -m 2>/dev/null | sed -e 's/aarch64.*/arm64/')
138fi
139VADDR64=0
140echo "$ARCH64STR" | grep "$ARCH" &>/dev/null && VADDR64=1
141
142# Usage: run_test [test binary] [arbitrary test arguments...]
143run_test() {
144	if test_selected ${CATEGORY}; then
145		local title="running $*"
146		local sep=$(echo -n "$title" | tr "[:graph:][:space:]" -)
147		printf "%s\n%s\n%s\n" "$sep" "$title" "$sep"
148
149		"$@"
150		local ret=$?
151		if [ $ret -eq 0 ]; then
152			echo "[PASS]"
153		elif [ $ret -eq $ksft_skip ]; then
154			echo "[SKIP]"
155			exitcode=$ksft_skip
156		else
157			echo "[FAIL]"
158			exitcode=1
159		fi
160	fi # test_selected
161}
162
163CATEGORY="hugetlb" run_test ./hugepage-mmap
164
165shmmax=$(cat /proc/sys/kernel/shmmax)
166shmall=$(cat /proc/sys/kernel/shmall)
167echo 268435456 > /proc/sys/kernel/shmmax
168echo 4194304 > /proc/sys/kernel/shmall
169CATEGORY="hugetlb" run_test ./hugepage-shm
170echo "$shmmax" > /proc/sys/kernel/shmmax
171echo "$shmall" > /proc/sys/kernel/shmall
172
173CATEGORY="hugetlb" run_test ./map_hugetlb
174CATEGORY="hugetlb" run_test ./hugepage-mremap
175CATEGORY="hugetlb" run_test ./hugepage-vmemmap
176CATEGORY="hugetlb" run_test ./hugetlb-madvise
177
178if test_selected "hugetlb"; then
179	echo "NOTE: These hugetlb tests provide minimal coverage.  Use"
180	echo "      https://github.com/libhugetlbfs/libhugetlbfs.git for"
181	echo "      hugetlb regression testing."
182fi
183
184CATEGORY="mmap" run_test ./map_fixed_noreplace
185
186# get_user_pages_fast() benchmark
187CATEGORY="gup_test" run_test ./gup_test -u
188# pin_user_pages_fast() benchmark
189CATEGORY="gup_test" run_test ./gup_test -a
190# Dump pages 0, 19, and 4096, using pin_user_pages:
191CATEGORY="gup_test" run_test ./gup_test -ct -F 0x1 0 19 0x1000
192
193uffd_mods=("" ":dev")
194for mod in "${uffd_mods[@]}"; do
195	CATEGORY="userfaultfd" run_test ./userfaultfd anon${mod} 20 16
196	# Hugetlb tests require source and destination huge pages. Pass in half
197	# the size ($half_ufd_size_MB), which is used for *each*.
198	CATEGORY="userfaultfd" run_test ./userfaultfd hugetlb${mod} "$half_ufd_size_MB" 32
199	CATEGORY="userfaultfd" run_test ./userfaultfd hugetlb_shared${mod} "$half_ufd_size_MB" 32
200	CATEGORY="userfaultfd" run_test ./userfaultfd shmem${mod} 20 16
201done
202
203#cleanup
204echo "$nr_hugepgs" > /proc/sys/vm/nr_hugepages
205
206CATEGORY="compaction" run_test ./compaction_test
207
208CATEGORY="mlock" run_test sudo -u nobody ./on-fault-limit
209
210CATEGORY="mmap" run_test ./map_populate
211
212CATEGORY="mlock" run_test ./mlock-random-test
213
214CATEGORY="mlock" run_test ./mlock2-tests
215
216CATEGORY="process_mrelease" run_test ./mrelease_test
217
218CATEGORY="mremap" run_test ./mremap_test
219
220CATEGORY="hugetlb" run_test ./thuge-gen
221
222if [ $VADDR64 -ne 0 ]; then
223	CATEGORY="hugevm" run_test ./virtual_address_range
224
225	# virtual address 128TB switch test
226	CATEGORY="hugevm" run_test ./va_128TBswitch.sh
227fi # VADDR64
228
229# vmalloc stability smoke test
230CATEGORY="vmalloc" run_test ./test_vmalloc.sh smoke
231
232CATEGORY="mremap" run_test ./mremap_dontunmap
233
234CATEGORY="hmm" run_test ./test_hmm.sh smoke
235
236# MADV_POPULATE_READ and MADV_POPULATE_WRITE tests
237CATEGORY="madv_populate" run_test ./madv_populate
238
239CATEGORY="memfd_secret" run_test ./memfd_secret
240
241# KSM MADV_MERGEABLE test with 10 identical pages
242CATEGORY="ksm" run_test ./ksm_tests -M -p 10
243# KSM unmerge test
244CATEGORY="ksm" run_test ./ksm_tests -U
245# KSM test with 10 zero pages and use_zero_pages = 0
246CATEGORY="ksm" run_test ./ksm_tests -Z -p 10 -z 0
247# KSM test with 10 zero pages and use_zero_pages = 1
248CATEGORY="ksm" run_test ./ksm_tests -Z -p 10 -z 1
249# KSM test with 2 NUMA nodes and merge_across_nodes = 1
250CATEGORY="ksm_numa" run_test ./ksm_tests -N -m 1
251# KSM test with 2 NUMA nodes and merge_across_nodes = 0
252CATEGORY="ksm_numa" run_test ./ksm_tests -N -m 0
253
254CATEGORY="ksm" run_test ./ksm_functional_tests
255
256run_test ./ksm_functional_tests
257
258# protection_keys tests
259if [ -x ./protection_keys_32 ]
260then
261	CATEGORY="pkey" run_test ./protection_keys_32
262fi
263
264if [ -x ./protection_keys_64 ]
265then
266	CATEGORY="pkey" run_test ./protection_keys_64
267fi
268
269CATEGORY="soft_dirty" run_test ./soft-dirty
270
271# COW tests
272CATEGORY="cow" run_test ./cow
273
274exit $exitcode
275