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_total=0 9count_pass=0 10count_fail=0 11count_skip=0 12exitcode=0 13 14usage() { 15 cat <<EOF 16usage: ${BASH_SOURCE[0]:-$0} [ options ] 17 18 -a: run all tests, including extra ones 19 -t: specify specific categories to tests to run 20 -h: display this message 21 -n: disable TAP output 22 23The default behavior is to run required tests only. If -a is specified, 24will run all tests. 25 26Alternatively, specific groups tests can be run by passing a string 27to the -t argument containing one or more of the following categories 28separated by spaces: 29- mmap 30 tests for mmap(2) 31- gup_test 32 tests for gup 33- userfaultfd 34 tests for userfaultfd(2) 35- compaction 36 a test for the patch "Allow compaction of unevictable pages" 37- mlock 38 tests for mlock(2) 39- mremap 40 tests for mremap(2) 41- hugevm 42 tests for very large virtual address space 43- vmalloc 44 vmalloc smoke tests 45- hmm 46 hmm smoke tests 47- madv_populate 48 test memadvise(2) MADV_POPULATE_{READ,WRITE} options 49- memfd_secret 50 test memfd_secret(2) 51- process_mrelease 52 test process_mrelease(2) 53- ksm 54 ksm tests that do not require >=2 NUMA nodes 55- ksm_numa 56 ksm tests that require >=2 NUMA nodes 57- pkey 58 memory protection key tests 59- soft_dirty 60 test soft dirty page bit semantics 61- pagemap 62 test pagemap_scan IOCTL 63- cow 64 test copy-on-write semantics 65- thp 66 test transparent huge pages 67- hugetlb 68 test hugetlbfs huge pages 69- migration 70 invoke move_pages(2) to exercise the migration entry code 71 paths in the kernel 72- mkdirty 73 test handling of code that might set PTE/PMD dirty in 74 read-only VMAs 75- mdwe 76 test prctl(PR_SET_MDWE, ...) 77 78example: ./run_vmtests.sh -t "hmm mmap ksm" 79EOF 80 exit 0 81} 82 83RUN_ALL=false 84TAP_PREFIX="# " 85 86while getopts "aht:n" OPT; do 87 case ${OPT} in 88 "a") RUN_ALL=true ;; 89 "h") usage ;; 90 "t") VM_SELFTEST_ITEMS=${OPTARG} ;; 91 "n") TAP_PREFIX= ;; 92 esac 93done 94shift $((OPTIND -1)) 95 96# default behavior: run all tests 97VM_SELFTEST_ITEMS=${VM_SELFTEST_ITEMS:-default} 98 99test_selected() { 100 if [ "$VM_SELFTEST_ITEMS" == "default" ]; then 101 # If no VM_SELFTEST_ITEMS are specified, run all tests 102 return 0 103 fi 104 # If test selected argument is one of the test items 105 if [[ " ${VM_SELFTEST_ITEMS[*]} " =~ " ${1} " ]]; then 106 return 0 107 else 108 return 1 109 fi 110} 111 112run_gup_matrix() { 113 # -t: thp=on, -T: thp=off, -H: hugetlb=on 114 local hugetlb_mb=$(( needmem_KB / 1024 )) 115 116 for huge in -t -T "-H -m $hugetlb_mb"; do 117 # -u: gup-fast, -U: gup-basic, -a: pin-fast, -b: pin-basic, -L: pin-longterm 118 for test_cmd in -u -U -a -b -L; do 119 # -w: write=1, -W: write=0 120 for write in -w -W; do 121 # -S: shared 122 for share in -S " "; do 123 # -n: How many pages to fetch together? 512 is special 124 # because it's default thp size (or 2M on x86), 123 to 125 # just test partial gup when hit a huge in whatever form 126 for num in "-n 1" "-n 512" "-n 123"; do 127 CATEGORY="gup_test" run_test ./gup_test \ 128 $huge $test_cmd $write $share $num 129 done 130 done 131 done 132 done 133 done 134} 135 136# get huge pagesize and freepages from /proc/meminfo 137while read -r name size unit; do 138 if [ "$name" = "HugePages_Free:" ]; then 139 freepgs="$size" 140 fi 141 if [ "$name" = "Hugepagesize:" ]; then 142 hpgsize_KB="$size" 143 fi 144done < /proc/meminfo 145 146# Simple hugetlbfs tests have a hardcoded minimum requirement of 147# huge pages totaling 256MB (262144KB) in size. The userfaultfd 148# hugetlb test requires a minimum of 2 * nr_cpus huge pages. Take 149# both of these requirements into account and attempt to increase 150# number of huge pages available. 151nr_cpus=$(nproc) 152hpgsize_MB=$((hpgsize_KB / 1024)) 153half_ufd_size_MB=$((((nr_cpus * hpgsize_MB + 127) / 128) * 128)) 154needmem_KB=$((half_ufd_size_MB * 2 * 1024)) 155 156# set proper nr_hugepages 157if [ -n "$freepgs" ] && [ -n "$hpgsize_KB" ]; then 158 nr_hugepgs=$(cat /proc/sys/vm/nr_hugepages) 159 needpgs=$((needmem_KB / hpgsize_KB)) 160 tries=2 161 while [ "$tries" -gt 0 ] && [ "$freepgs" -lt "$needpgs" ]; do 162 lackpgs=$((needpgs - freepgs)) 163 echo 3 > /proc/sys/vm/drop_caches 164 if ! echo $((lackpgs + nr_hugepgs)) > /proc/sys/vm/nr_hugepages; then 165 echo "Please run this test as root" 166 exit $ksft_skip 167 fi 168 while read -r name size unit; do 169 if [ "$name" = "HugePages_Free:" ]; then 170 freepgs=$size 171 fi 172 done < /proc/meminfo 173 tries=$((tries - 1)) 174 done 175 if [ "$freepgs" -lt "$needpgs" ]; then 176 printf "Not enough huge pages available (%d < %d)\n" \ 177 "$freepgs" "$needpgs" 178 exit 1 179 fi 180else 181 echo "no hugetlbfs support in kernel?" 182 exit 1 183fi 184 185# filter 64bit architectures 186ARCH64STR="arm64 ia64 mips64 parisc64 ppc64 ppc64le riscv64 s390x sparc64 x86_64" 187if [ -z "$ARCH" ]; then 188 ARCH=$(uname -m 2>/dev/null | sed -e 's/aarch64.*/arm64/') 189fi 190VADDR64=0 191echo "$ARCH64STR" | grep "$ARCH" &>/dev/null && VADDR64=1 192 193tap_prefix() { 194 sed -e "s/^/${TAP_PREFIX}/" 195} 196 197tap_output() { 198 if [[ ! -z "$TAP_PREFIX" ]]; then 199 read str 200 echo $str 201 fi 202} 203 204pretty_name() { 205 echo "$*" | sed -e 's/^\(bash \)\?\.\///' 206} 207 208# Usage: run_test [test binary] [arbitrary test arguments...] 209run_test() { 210 if test_selected ${CATEGORY}; then 211 # On memory constrainted systems some tests can fail to allocate hugepages. 212 # perform some cleanup before the test for a higher success rate. 213 if [ ${CATEGORY} == "thp" ] | [ ${CATEGORY} == "hugetlb" ]; then 214 echo 3 > /proc/sys/vm/drop_caches 215 sleep 2 216 echo 1 > /proc/sys/vm/compact_memory 217 sleep 2 218 fi 219 220 local test=$(pretty_name "$*") 221 local title="running $*" 222 local sep=$(echo -n "$title" | tr "[:graph:][:space:]" -) 223 printf "%s\n%s\n%s\n" "$sep" "$title" "$sep" | tap_prefix 224 225 ("$@" 2>&1) | tap_prefix 226 local ret=${PIPESTATUS[0]} 227 count_total=$(( count_total + 1 )) 228 if [ $ret -eq 0 ]; then 229 count_pass=$(( count_pass + 1 )) 230 echo "[PASS]" | tap_prefix 231 echo "ok ${count_total} ${test}" | tap_output 232 elif [ $ret -eq $ksft_skip ]; then 233 count_skip=$(( count_skip + 1 )) 234 echo "[SKIP]" | tap_prefix 235 echo "ok ${count_total} ${test} # SKIP" | tap_output 236 exitcode=$ksft_skip 237 else 238 count_fail=$(( count_fail + 1 )) 239 echo "[FAIL]" | tap_prefix 240 echo "not ok ${count_total} ${test} # exit=$ret" | tap_output 241 exitcode=1 242 fi 243 fi # test_selected 244} 245 246echo "TAP version 13" | tap_output 247 248CATEGORY="hugetlb" run_test ./hugepage-mmap 249 250shmmax=$(cat /proc/sys/kernel/shmmax) 251shmall=$(cat /proc/sys/kernel/shmall) 252echo 268435456 > /proc/sys/kernel/shmmax 253echo 4194304 > /proc/sys/kernel/shmall 254CATEGORY="hugetlb" run_test ./hugepage-shm 255echo "$shmmax" > /proc/sys/kernel/shmmax 256echo "$shmall" > /proc/sys/kernel/shmall 257 258CATEGORY="hugetlb" run_test ./map_hugetlb 259CATEGORY="hugetlb" run_test ./hugepage-mremap 260CATEGORY="hugetlb" run_test ./hugepage-vmemmap 261CATEGORY="hugetlb" run_test ./hugetlb-madvise 262 263nr_hugepages_tmp=$(cat /proc/sys/vm/nr_hugepages) 264# For this test, we need one and just one huge page 265echo 1 > /proc/sys/vm/nr_hugepages 266CATEGORY="hugetlb" run_test ./hugetlb_fault_after_madv 267CATEGORY="hugetlb" run_test ./hugetlb_madv_vs_map 268# Restore the previous number of huge pages, since further tests rely on it 269echo "$nr_hugepages_tmp" > /proc/sys/vm/nr_hugepages 270 271if test_selected "hugetlb"; then 272 echo "NOTE: These hugetlb tests provide minimal coverage. Use" | tap_prefix 273 echo " https://github.com/libhugetlbfs/libhugetlbfs.git for" | tap_prefix 274 echo " hugetlb regression testing." | tap_prefix 275fi 276 277CATEGORY="mmap" run_test ./map_fixed_noreplace 278 279if $RUN_ALL; then 280 run_gup_matrix 281else 282 # get_user_pages_fast() benchmark 283 CATEGORY="gup_test" run_test ./gup_test -u 284 # pin_user_pages_fast() benchmark 285 CATEGORY="gup_test" run_test ./gup_test -a 286fi 287# Dump pages 0, 19, and 4096, using pin_user_pages: 288CATEGORY="gup_test" run_test ./gup_test -ct -F 0x1 0 19 0x1000 289CATEGORY="gup_test" run_test ./gup_longterm 290 291CATEGORY="userfaultfd" run_test ./uffd-unit-tests 292uffd_stress_bin=./uffd-stress 293CATEGORY="userfaultfd" run_test ${uffd_stress_bin} anon 20 16 294# Hugetlb tests require source and destination huge pages. Pass in half 295# the size ($half_ufd_size_MB), which is used for *each*. 296CATEGORY="userfaultfd" run_test ${uffd_stress_bin} hugetlb "$half_ufd_size_MB" 32 297CATEGORY="userfaultfd" run_test ${uffd_stress_bin} hugetlb-private "$half_ufd_size_MB" 32 298CATEGORY="userfaultfd" run_test ${uffd_stress_bin} shmem 20 16 299CATEGORY="userfaultfd" run_test ${uffd_stress_bin} shmem-private 20 16 300 301#cleanup 302echo "$nr_hugepgs" > /proc/sys/vm/nr_hugepages 303 304CATEGORY="compaction" run_test ./compaction_test 305 306CATEGORY="mlock" run_test sudo -u nobody ./on-fault-limit 307 308CATEGORY="mmap" run_test ./map_populate 309 310CATEGORY="mlock" run_test ./mlock-random-test 311 312CATEGORY="mlock" run_test ./mlock2-tests 313 314CATEGORY="process_mrelease" run_test ./mrelease_test 315 316CATEGORY="mremap" run_test ./mremap_test 317 318CATEGORY="hugetlb" run_test ./thuge-gen 319 320if [ $VADDR64 -ne 0 ]; then 321 322 # set overcommit_policy as OVERCOMMIT_ALWAYS so that kernel 323 # allows high virtual address allocation requests independent 324 # of platform's physical memory. 325 326 prev_policy=$(cat /proc/sys/vm/overcommit_memory) 327 echo 1 > /proc/sys/vm/overcommit_memory 328 CATEGORY="hugevm" run_test ./virtual_address_range 329 echo $prev_policy > /proc/sys/vm/overcommit_memory 330 331 # va high address boundary switch test 332 ARCH_ARM64="arm64" 333 prev_nr_hugepages=$(cat /proc/sys/vm/nr_hugepages) 334 if [ "$ARCH" == "$ARCH_ARM64" ]; then 335 echo 6 > /proc/sys/vm/nr_hugepages 336 fi 337 CATEGORY="hugevm" run_test bash ./va_high_addr_switch.sh 338 if [ "$ARCH" == "$ARCH_ARM64" ]; then 339 echo $prev_nr_hugepages > /proc/sys/vm/nr_hugepages 340 fi 341fi # VADDR64 342 343# vmalloc stability smoke test 344CATEGORY="vmalloc" run_test bash ./test_vmalloc.sh smoke 345 346CATEGORY="mremap" run_test ./mremap_dontunmap 347 348CATEGORY="hmm" run_test bash ./test_hmm.sh smoke 349 350# MADV_POPULATE_READ and MADV_POPULATE_WRITE tests 351CATEGORY="madv_populate" run_test ./madv_populate 352 353(echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope 2>&1) | tap_prefix 354CATEGORY="memfd_secret" run_test ./memfd_secret 355 356# KSM KSM_MERGE_TIME_HUGE_PAGES test with size of 100 357CATEGORY="ksm" run_test ./ksm_tests -H -s 100 358# KSM KSM_MERGE_TIME test with size of 100 359CATEGORY="ksm" run_test ./ksm_tests -P -s 100 360# KSM MADV_MERGEABLE test with 10 identical pages 361CATEGORY="ksm" run_test ./ksm_tests -M -p 10 362# KSM unmerge test 363CATEGORY="ksm" run_test ./ksm_tests -U 364# KSM test with 10 zero pages and use_zero_pages = 0 365CATEGORY="ksm" run_test ./ksm_tests -Z -p 10 -z 0 366# KSM test with 10 zero pages and use_zero_pages = 1 367CATEGORY="ksm" run_test ./ksm_tests -Z -p 10 -z 1 368# KSM test with 2 NUMA nodes and merge_across_nodes = 1 369CATEGORY="ksm_numa" run_test ./ksm_tests -N -m 1 370# KSM test with 2 NUMA nodes and merge_across_nodes = 0 371CATEGORY="ksm_numa" run_test ./ksm_tests -N -m 0 372 373CATEGORY="ksm" run_test ./ksm_functional_tests 374 375# protection_keys tests 376if [ -x ./protection_keys_32 ] 377then 378 CATEGORY="pkey" run_test ./protection_keys_32 379fi 380 381if [ -x ./protection_keys_64 ] 382then 383 CATEGORY="pkey" run_test ./protection_keys_64 384fi 385 386if [ -x ./soft-dirty ] 387then 388 CATEGORY="soft_dirty" run_test ./soft-dirty 389fi 390 391CATEGORY="pagemap" run_test ./pagemap_ioctl 392 393# COW tests 394CATEGORY="cow" run_test ./cow 395 396CATEGORY="thp" run_test ./khugepaged 397 398CATEGORY="thp" run_test ./khugepaged -s 2 399 400CATEGORY="thp" run_test ./transhuge-stress -d 20 401 402CATEGORY="thp" run_test ./split_huge_page_test 403 404CATEGORY="migration" run_test ./migration 405 406CATEGORY="mkdirty" run_test ./mkdirty 407 408CATEGORY="mdwe" run_test ./mdwe_test 409 410echo "SUMMARY: PASS=${count_pass} SKIP=${count_skip} FAIL=${count_fail}" | tap_prefix 411echo "1..${count_total}" | tap_output 412 413exit $exitcode 414