1d60bc771SMichal Berger#!/usr/bin/env bash 2eb53c232Spaul luse# SPDX-License-Identifier: BSD-3-Clause 3eb53c232Spaul luse# Copyright (C) 2020 Intel Corporation 4eb53c232Spaul luse# All rights reserved. 5eb53c232Spaul luse# 6d60bc771SMichal Bergertestdir=$(readlink -f "$(dirname "$0")") 7d60bc771SMichal Bergerrootdir=$(readlink -f "$testdir/../../") 8d60bc771SMichal Bergersource "$testdir/common.sh" 9d60bc771SMichal Berger 10d60bc771SMichal Bergerdeclare -a nodes_sys=() 11d60bc771SMichal Berger 12c9c7c281SJosh Sorefdeclare -i default_hugepages=0 13d60bc771SMichal Bergerdeclare -i no_nodes=0 14d60bc771SMichal Bergerdeclare -i nr_hugepages=0 15d60bc771SMichal Berger 16c9c7c281SJosh Sorefdefault_hugepages=$(get_meminfo Hugepagesize) 17c9c7c281SJosh Sorefdefault_huge_nr=/sys/kernel/mm/hugepages/hugepages-${default_hugepages}kB/nr_hugepages 18d60bc771SMichal Bergerglobal_huge_nr=/proc/sys/vm/nr_hugepages 19d60bc771SMichal Berger 20227428c3SMichal Berger# Make sure environment doesn't affect the tests 21227428c3SMichal Bergerunset -v HUGEMEM 22227428c3SMichal Bergerunset -v HUGENODE 23227428c3SMichal Bergerunset -v NRHUGE 24227428c3SMichal Berger 25d60bc771SMichal Bergerget_nodes() { 26d60bc771SMichal Berger local node 27d60bc771SMichal Berger 28d60bc771SMichal Berger for node in /sys/devices/system/node/node+([0-9]); do 29c9c7c281SJosh Soref nodes_sys[${node##*node}]=$(< "$node/hugepages/hugepages-${default_hugepages}kB/nr_hugepages") 30d60bc771SMichal Berger done 31d60bc771SMichal Berger no_nodes=${#nodes_sys[@]} 32d60bc771SMichal Berger ((no_nodes > 0)) 33d60bc771SMichal Berger} 34d60bc771SMichal Berger 35d60bc771SMichal Bergerclear_hp() { 36d60bc771SMichal Berger local node hp 37d60bc771SMichal Berger 38d60bc771SMichal Berger for node in "${!nodes_sys[@]}"; do 39d60bc771SMichal Berger for hp in "/sys/devices/system/node/node$node/hugepages/hugepages-"*; do 40d60bc771SMichal Berger echo 0 > "$hp/nr_hugepages" 41d60bc771SMichal Berger done 42d60bc771SMichal Berger done 43d60bc771SMichal Berger 44d60bc771SMichal Berger export CLEAR_HUGE=yes 45d60bc771SMichal Berger} 46d60bc771SMichal Berger 47d60bc771SMichal Bergerget_test_nr_hugepages() { 48d60bc771SMichal Berger local size=$1 # kB 49d60bc771SMichal Berger if (($# > 1)); then 50d60bc771SMichal Berger shift 51d60bc771SMichal Berger local node_ids=("$@") 52d60bc771SMichal Berger fi 53d60bc771SMichal Berger 54c9c7c281SJosh Soref ((size >= default_hugepages)) 55d60bc771SMichal Berger 56c9c7c281SJosh Soref nr_hugepages=$(((size + default_hugepages - 1) / default_hugepages)) 57d60bc771SMichal Berger get_test_nr_hugepages_per_node "${node_ids[@]}" 58d60bc771SMichal Berger} 59d60bc771SMichal Berger 60d60bc771SMichal Bergerget_test_nr_hugepages_per_node() { 61d60bc771SMichal Berger local user_nodes=("$@") 62d60bc771SMichal Berger 63d60bc771SMichal Berger local _nr_hugepages=$nr_hugepages 64d60bc771SMichal Berger local _no_nodes=$no_nodes 65d60bc771SMichal Berger 66d60bc771SMichal Berger local -g nodes_test=() 67d60bc771SMichal Berger 68d60bc771SMichal Berger if ((${#user_nodes[@]} > 0)); then 69d60bc771SMichal Berger for _no_nodes in "${user_nodes[@]}"; do 70d60bc771SMichal Berger nodes_test[_no_nodes]=$nr_hugepages 71d60bc771SMichal Berger done 72d60bc771SMichal Berger return 0 73d60bc771SMichal Berger elif ((${#nodes_hp[@]} > 0)); then 74d60bc771SMichal Berger for _no_nodes in "${!nodes_hp[@]}"; do 75d60bc771SMichal Berger nodes_test[_no_nodes]=${nodes_hp[_no_nodes]} 76d60bc771SMichal Berger done 77d60bc771SMichal Berger return 0 78d60bc771SMichal Berger fi 79d60bc771SMichal Berger 80d60bc771SMichal Berger while ((_no_nodes > 0)); do 81d60bc771SMichal Berger nodes_test[_no_nodes - 1]=$((_nr_hugepages / _no_nodes)) 82d60bc771SMichal Berger : $((_nr_hugepages -= nodes_test[_no_nodes - 1])) 83d60bc771SMichal Berger : $((--_no_nodes)) 84d60bc771SMichal Berger done 85d60bc771SMichal Berger} 86d60bc771SMichal Berger 87d60bc771SMichal Bergerverify_nr_hugepages() { 88d60bc771SMichal Berger local node 89d60bc771SMichal Berger local sorted_t 90d60bc771SMichal Berger local sorted_s 91327f69eaSMichal Berger local surp 92327f69eaSMichal Berger local resv 93327f69eaSMichal Berger local anon 94327f69eaSMichal Berger 95327f69eaSMichal Berger if [[ $(< /sys/kernel/mm/transparent_hugepage/enabled) != *"[never]"* ]]; then 96327f69eaSMichal Berger anon=$(get_meminfo AnonHugePages) 97327f69eaSMichal Berger fi 98327f69eaSMichal Berger surp=$(get_meminfo HugePages_Surp) 99327f69eaSMichal Berger resv=$(get_meminfo HugePages_Rsvd) 100d60bc771SMichal Berger 101d60bc771SMichal Berger echo "nr_hugepages=$nr_hugepages" 102327f69eaSMichal Berger echo "resv_hugepages=$resv" 103327f69eaSMichal Berger echo "surplus_hugepages=$surp" 104327f69eaSMichal Berger echo "anon_hugepages=${anon:-disabled}" 105327f69eaSMichal Berger 106327f69eaSMichal Berger (($(< "$default_huge_nr") == nr_hugepages + surp + resv)) 107327f69eaSMichal Berger # This knob doesn't account for the surp, resv hugepages 108d60bc771SMichal Berger (($(< "$global_huge_nr") == nr_hugepages)) 109327f69eaSMichal Berger (($(get_meminfo HugePages_Total) == nr_hugepages + surp + resv)) 110d60bc771SMichal Berger 111d60bc771SMichal Berger get_nodes 112d60bc771SMichal Berger 113327f69eaSMichal Berger # Take global resv and per-node surplus hugepages into account 114327f69eaSMichal Berger for node in "${!nodes_test[@]}"; do 115327f69eaSMichal Berger ((nodes_test[node] += resv)) 116327f69eaSMichal Berger ((nodes_test[node] += $(get_meminfo HugePages_Surp "$node"))) 117327f69eaSMichal Berger done 118327f69eaSMichal Berger 119d60bc771SMichal Berger # There's no obvious way of determining which NUMA node is going to end 120d60bc771SMichal Berger # up with an odd number of hugepages in case such number was actually 121d60bc771SMichal Berger # allocated by the kernel. Considering that, let's simply check if our 122c9c7c281SJosh Soref # expectation is met by sorting and comparing it with nr of hugepages that 123d60bc771SMichal Berger # was actually allocated on each node. 124d60bc771SMichal Berger 125d60bc771SMichal Berger for node in "${!nodes_test[@]}"; do 126d60bc771SMichal Berger sorted_t[nodes_test[node]]=1 sorted_s[nodes_sys[node]]=1 127327f69eaSMichal Berger echo "node$node=${nodes_sys[node]} expecting ${nodes_test[node]}" 128d60bc771SMichal Berger done 129d60bc771SMichal Berger [[ ${!sorted_s[*]} == "${!sorted_t[*]}" ]] 130d60bc771SMichal Berger} 131d60bc771SMichal Berger 132d60bc771SMichal Berger# Test cases 133*0070858eSMichal Bergersingle_node_setup() { 134*0070858eSMichal Berger # HUGEMEM (2G) alloc on node0 135227428c3SMichal Berger get_test_nr_hugepages $((2048 * 1024)) 0 136*0070858eSMichal Berger NRHUGE=$nr_hugepages HUGENODE=0 setup output 137d60bc771SMichal Berger verify_nr_hugepages 138d60bc771SMichal Berger} 139d60bc771SMichal Berger 140d60bc771SMichal Bergereven_2G_alloc() { 141d60bc771SMichal Berger # 2G alloc spread across N nodes 142d60bc771SMichal Berger get_test_nr_hugepages $((2048 * 1024)) 143*0070858eSMichal Berger NRHUGE=$nr_hugepages setup output 144d60bc771SMichal Berger verify_nr_hugepages 145d60bc771SMichal Berger} 146d60bc771SMichal Berger 147d60bc771SMichal Bergerodd_alloc() { 148d60bc771SMichal Berger # Odd 2049MB alloc across N nodes 149d60bc771SMichal Berger get_test_nr_hugepages $((2049 * 1024)) 150*0070858eSMichal Berger HUGEMEM=2049 setup output 151d60bc771SMichal Berger verify_nr_hugepages 152d60bc771SMichal Berger} 153d60bc771SMichal Berger 154d60bc771SMichal Bergercustom_alloc() { 1553f674e1eSMichal Berger # Custom alloc: node0 == 1GB [node1 == 2 GB] 156d60bc771SMichal Berger 157d60bc771SMichal Berger local IFS="," 158d60bc771SMichal Berger 159d60bc771SMichal Berger local node 160d60bc771SMichal Berger local nodes_hp=() 161d60bc771SMichal Berger 1623f674e1eSMichal Berger local nr_hugepages=0 _nr_hugepages=0 163d60bc771SMichal Berger 1643f674e1eSMichal Berger get_test_nr_hugepages $((1024 * 1024)) 1653f674e1eSMichal Berger nodes_hp[0]=$nr_hugepages 166d60bc771SMichal Berger if ((${#nodes_sys[@]} > 1)); then 1673f674e1eSMichal Berger get_test_nr_hugepages $((2048 * 1024)) 1683f674e1eSMichal Berger nodes_hp[1]=$nr_hugepages 169d60bc771SMichal Berger fi 170d60bc771SMichal Berger 171d60bc771SMichal Berger for node in "${!nodes_hp[@]}"; do 172d60bc771SMichal Berger HUGENODE+=("nodes_hp[$node]=${nodes_hp[node]}") 1733f674e1eSMichal Berger ((_nr_hugepages += nodes_hp[node])) 174d60bc771SMichal Berger done 175d60bc771SMichal Berger 176d60bc771SMichal Berger get_test_nr_hugepages_per_node 17745dc5f12SMichal Berger HUGENODE="${HUGENODE[*]}" setup output 1783f674e1eSMichal Berger nr_hugepages=$_nr_hugepages verify_nr_hugepages 179d60bc771SMichal Berger} 180d60bc771SMichal Berger 18128bfb876SMichal Bergerno_shrink_alloc() { 182*0070858eSMichal Berger # HUGEMEM (2G) alloc on node0 18328bfb876SMichal Berger # attempt to shrink by half: 2G should remain 18428bfb876SMichal Berger 18528bfb876SMichal Berger get_test_nr_hugepages $((2048 * 1024)) 0 18628bfb876SMichal Berger 18728bfb876SMichal Berger # Verify the default first 188*0070858eSMichal Berger NRHUGE=$nr_hugepages HUGENODE=0 setup output 18928bfb876SMichal Berger verify_nr_hugepages 19028bfb876SMichal Berger 19128bfb876SMichal Berger # Now attempt to shrink the hp number 192*0070858eSMichal Berger CLEAR_HUGE=no NRHUGE=$((nr_hugepages / 2)) HUGENODE=0 setup output 19328bfb876SMichal Berger # 2G should remain 19428bfb876SMichal Berger verify_nr_hugepages 19528bfb876SMichal Berger} 19628bfb876SMichal Berger 197d60bc771SMichal Bergerget_nodes 198d60bc771SMichal Bergerclear_hp 199d60bc771SMichal Berger 200*0070858eSMichal Bergerrun_test "single_node_setup" single_node_setup 201d60bc771SMichal Bergerrun_test "even_2G_alloc" even_2G_alloc 202d60bc771SMichal Bergerrun_test "odd_alloc" odd_alloc 203d60bc771SMichal Bergerrun_test "custom_alloc" custom_alloc 20428bfb876SMichal Bergerrun_test "no_shrink_alloc" no_shrink_alloc 205d60bc771SMichal Berger 206d60bc771SMichal Bergerclear_hp 207