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