cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

charge_reserved_hugetlb.sh (17365B)


      1#!/bin/sh
      2# SPDX-License-Identifier: GPL-2.0
      3
      4# Kselftest framework requirement - SKIP code is 4.
      5ksft_skip=4
      6
      7set -e
      8
      9if [[ $(id -u) -ne 0 ]]; then
     10  echo "This test must be run as root. Skipping..."
     11  exit $ksft_skip
     12fi
     13
     14fault_limit_file=limit_in_bytes
     15reservation_limit_file=rsvd.limit_in_bytes
     16fault_usage_file=usage_in_bytes
     17reservation_usage_file=rsvd.usage_in_bytes
     18
     19if [[ "$1" == "-cgroup-v2" ]]; then
     20  cgroup2=1
     21  fault_limit_file=max
     22  reservation_limit_file=rsvd.max
     23  fault_usage_file=current
     24  reservation_usage_file=rsvd.current
     25fi
     26
     27if [[ $cgroup2 ]]; then
     28  cgroup_path=$(mount -t cgroup2 | head -1 | awk -e '{print $3}')
     29  if [[ -z "$cgroup_path" ]]; then
     30    cgroup_path=/dev/cgroup/memory
     31    mount -t cgroup2 none $cgroup_path
     32    do_umount=1
     33  fi
     34  echo "+hugetlb" >$cgroup_path/cgroup.subtree_control
     35else
     36  cgroup_path=$(mount -t cgroup | grep ",hugetlb" | awk -e '{print $3}')
     37  if [[ -z "$cgroup_path" ]]; then
     38    cgroup_path=/dev/cgroup/memory
     39    mount -t cgroup memory,hugetlb $cgroup_path
     40    do_umount=1
     41  fi
     42fi
     43export cgroup_path
     44
     45function cleanup() {
     46  if [[ $cgroup2 ]]; then
     47    echo $$ >$cgroup_path/cgroup.procs
     48  else
     49    echo $$ >$cgroup_path/tasks
     50  fi
     51
     52  if [[ -e /mnt/huge ]]; then
     53    rm -rf /mnt/huge/*
     54    umount /mnt/huge || echo error
     55    rmdir /mnt/huge
     56  fi
     57  if [[ -e $cgroup_path/hugetlb_cgroup_test ]]; then
     58    rmdir $cgroup_path/hugetlb_cgroup_test
     59  fi
     60  if [[ -e $cgroup_path/hugetlb_cgroup_test1 ]]; then
     61    rmdir $cgroup_path/hugetlb_cgroup_test1
     62  fi
     63  if [[ -e $cgroup_path/hugetlb_cgroup_test2 ]]; then
     64    rmdir $cgroup_path/hugetlb_cgroup_test2
     65  fi
     66  echo 0 >/proc/sys/vm/nr_hugepages
     67  echo CLEANUP DONE
     68}
     69
     70function expect_equal() {
     71  local expected="$1"
     72  local actual="$2"
     73  local error="$3"
     74
     75  if [[ "$expected" != "$actual" ]]; then
     76    echo "expected ($expected) != actual ($actual): $3"
     77    cleanup
     78    exit 1
     79  fi
     80}
     81
     82function get_machine_hugepage_size() {
     83  hpz=$(grep -i hugepagesize /proc/meminfo)
     84  kb=${hpz:14:-3}
     85  mb=$(($kb / 1024))
     86  echo $mb
     87}
     88
     89MB=$(get_machine_hugepage_size)
     90
     91function setup_cgroup() {
     92  local name="$1"
     93  local cgroup_limit="$2"
     94  local reservation_limit="$3"
     95
     96  mkdir $cgroup_path/$name
     97
     98  echo writing cgroup limit: "$cgroup_limit"
     99  echo "$cgroup_limit" >$cgroup_path/$name/hugetlb.${MB}MB.$fault_limit_file
    100
    101  echo writing reseravation limit: "$reservation_limit"
    102  echo "$reservation_limit" > \
    103    $cgroup_path/$name/hugetlb.${MB}MB.$reservation_limit_file
    104
    105  if [ -e "$cgroup_path/$name/cpuset.cpus" ]; then
    106    echo 0 >$cgroup_path/$name/cpuset.cpus
    107  fi
    108  if [ -e "$cgroup_path/$name/cpuset.mems" ]; then
    109    echo 0 >$cgroup_path/$name/cpuset.mems
    110  fi
    111}
    112
    113function wait_for_hugetlb_memory_to_get_depleted() {
    114  local cgroup="$1"
    115  local path="$cgroup_path/$cgroup/hugetlb.${MB}MB.$reservation_usage_file"
    116  # Wait for hugetlbfs memory to get depleted.
    117  while [ $(cat $path) != 0 ]; do
    118    echo Waiting for hugetlb memory to get depleted.
    119    cat $path
    120    sleep 0.5
    121  done
    122}
    123
    124function wait_for_hugetlb_memory_to_get_reserved() {
    125  local cgroup="$1"
    126  local size="$2"
    127
    128  local path="$cgroup_path/$cgroup/hugetlb.${MB}MB.$reservation_usage_file"
    129  # Wait for hugetlbfs memory to get written.
    130  while [ $(cat $path) != $size ]; do
    131    echo Waiting for hugetlb memory reservation to reach size $size.
    132    cat $path
    133    sleep 0.5
    134  done
    135}
    136
    137function wait_for_hugetlb_memory_to_get_written() {
    138  local cgroup="$1"
    139  local size="$2"
    140
    141  local path="$cgroup_path/$cgroup/hugetlb.${MB}MB.$fault_usage_file"
    142  # Wait for hugetlbfs memory to get written.
    143  while [ $(cat $path) != $size ]; do
    144    echo Waiting for hugetlb memory to reach size $size.
    145    cat $path
    146    sleep 0.5
    147  done
    148}
    149
    150function write_hugetlbfs_and_get_usage() {
    151  local cgroup="$1"
    152  local size="$2"
    153  local populate="$3"
    154  local write="$4"
    155  local path="$5"
    156  local method="$6"
    157  local private="$7"
    158  local expect_failure="$8"
    159  local reserve="$9"
    160
    161  # Function return values.
    162  reservation_failed=0
    163  oom_killed=0
    164  hugetlb_difference=0
    165  reserved_difference=0
    166
    167  local hugetlb_usage=$cgroup_path/$cgroup/hugetlb.${MB}MB.$fault_usage_file
    168  local reserved_usage=$cgroup_path/$cgroup/hugetlb.${MB}MB.$reservation_usage_file
    169
    170  local hugetlb_before=$(cat $hugetlb_usage)
    171  local reserved_before=$(cat $reserved_usage)
    172
    173  echo
    174  echo Starting:
    175  echo hugetlb_usage="$hugetlb_before"
    176  echo reserved_usage="$reserved_before"
    177  echo expect_failure is "$expect_failure"
    178
    179  output=$(mktemp)
    180  set +e
    181  if [[ "$method" == "1" ]] || [[ "$method" == 2 ]] ||
    182    [[ "$private" == "-r" ]] && [[ "$expect_failure" != 1 ]]; then
    183
    184    bash write_hugetlb_memory.sh "$size" "$populate" "$write" \
    185      "$cgroup" "$path" "$method" "$private" "-l" "$reserve" 2>&1 | tee $output &
    186
    187    local write_result=$?
    188    local write_pid=$!
    189
    190    until grep -q -i "DONE" $output; do
    191      echo waiting for DONE signal.
    192      if ! ps $write_pid > /dev/null
    193      then
    194        echo "FAIL: The write died"
    195        cleanup
    196        exit 1
    197      fi
    198      sleep 0.5
    199    done
    200
    201    echo ================= write_hugetlb_memory.sh output is:
    202    cat $output
    203    echo ================= end output.
    204
    205    if [[ "$populate" == "-o" ]] || [[ "$write" == "-w" ]]; then
    206      wait_for_hugetlb_memory_to_get_written "$cgroup" "$size"
    207    elif [[ "$reserve" != "-n" ]]; then
    208      wait_for_hugetlb_memory_to_get_reserved "$cgroup" "$size"
    209    else
    210      # This case doesn't produce visible effects, but we still have
    211      # to wait for the async process to start and execute...
    212      sleep 0.5
    213    fi
    214
    215    echo write_result is $write_result
    216  else
    217    bash write_hugetlb_memory.sh "$size" "$populate" "$write" \
    218      "$cgroup" "$path" "$method" "$private" "$reserve"
    219    local write_result=$?
    220
    221    if [[ "$reserve" != "-n" ]]; then
    222      wait_for_hugetlb_memory_to_get_reserved "$cgroup" "$size"
    223    fi
    224  fi
    225  set -e
    226
    227  if [[ "$write_result" == 1 ]]; then
    228    reservation_failed=1
    229  fi
    230
    231  # On linus/master, the above process gets SIGBUS'd on oomkill, with
    232  # return code 135. On earlier kernels, it gets actual oomkill, with return
    233  # code 137, so just check for both conditions in case we're testing
    234  # against an earlier kernel.
    235  if [[ "$write_result" == 135 ]] || [[ "$write_result" == 137 ]]; then
    236    oom_killed=1
    237  fi
    238
    239  local hugetlb_after=$(cat $hugetlb_usage)
    240  local reserved_after=$(cat $reserved_usage)
    241
    242  echo After write:
    243  echo hugetlb_usage="$hugetlb_after"
    244  echo reserved_usage="$reserved_after"
    245
    246  hugetlb_difference=$(($hugetlb_after - $hugetlb_before))
    247  reserved_difference=$(($reserved_after - $reserved_before))
    248}
    249
    250function cleanup_hugetlb_memory() {
    251  set +e
    252  local cgroup="$1"
    253  if [[ "$(pgrep -f write_to_hugetlbfs)" != "" ]]; then
    254    echo killing write_to_hugetlbfs
    255    killall -2 write_to_hugetlbfs
    256    wait_for_hugetlb_memory_to_get_depleted $cgroup
    257  fi
    258  set -e
    259
    260  if [[ -e /mnt/huge ]]; then
    261    rm -rf /mnt/huge/*
    262    umount /mnt/huge
    263    rmdir /mnt/huge
    264  fi
    265}
    266
    267function run_test() {
    268  local size=$(($1 * ${MB} * 1024 * 1024))
    269  local populate="$2"
    270  local write="$3"
    271  local cgroup_limit=$(($4 * ${MB} * 1024 * 1024))
    272  local reservation_limit=$(($5 * ${MB} * 1024 * 1024))
    273  local nr_hugepages="$6"
    274  local method="$7"
    275  local private="$8"
    276  local expect_failure="$9"
    277  local reserve="${10}"
    278
    279  # Function return values.
    280  hugetlb_difference=0
    281  reserved_difference=0
    282  reservation_failed=0
    283  oom_killed=0
    284
    285  echo nr hugepages = "$nr_hugepages"
    286  echo "$nr_hugepages" >/proc/sys/vm/nr_hugepages
    287
    288  setup_cgroup "hugetlb_cgroup_test" "$cgroup_limit" "$reservation_limit"
    289
    290  mkdir -p /mnt/huge
    291  mount -t hugetlbfs -o pagesize=${MB}M,size=256M none /mnt/huge
    292
    293  write_hugetlbfs_and_get_usage "hugetlb_cgroup_test" "$size" "$populate" \
    294    "$write" "/mnt/huge/test" "$method" "$private" "$expect_failure" \
    295    "$reserve"
    296
    297  cleanup_hugetlb_memory "hugetlb_cgroup_test"
    298
    299  local final_hugetlb=$(cat $cgroup_path/hugetlb_cgroup_test/hugetlb.${MB}MB.$fault_usage_file)
    300  local final_reservation=$(cat $cgroup_path/hugetlb_cgroup_test/hugetlb.${MB}MB.$reservation_usage_file)
    301
    302  echo $hugetlb_difference
    303  echo $reserved_difference
    304  expect_equal "0" "$final_hugetlb" "final hugetlb is not zero"
    305  expect_equal "0" "$final_reservation" "final reservation is not zero"
    306}
    307
    308function run_multiple_cgroup_test() {
    309  local size1="$1"
    310  local populate1="$2"
    311  local write1="$3"
    312  local cgroup_limit1="$4"
    313  local reservation_limit1="$5"
    314
    315  local size2="$6"
    316  local populate2="$7"
    317  local write2="$8"
    318  local cgroup_limit2="$9"
    319  local reservation_limit2="${10}"
    320
    321  local nr_hugepages="${11}"
    322  local method="${12}"
    323  local private="${13}"
    324  local expect_failure="${14}"
    325  local reserve="${15}"
    326
    327  # Function return values.
    328  hugetlb_difference1=0
    329  reserved_difference1=0
    330  reservation_failed1=0
    331  oom_killed1=0
    332
    333  hugetlb_difference2=0
    334  reserved_difference2=0
    335  reservation_failed2=0
    336  oom_killed2=0
    337
    338  echo nr hugepages = "$nr_hugepages"
    339  echo "$nr_hugepages" >/proc/sys/vm/nr_hugepages
    340
    341  setup_cgroup "hugetlb_cgroup_test1" "$cgroup_limit1" "$reservation_limit1"
    342  setup_cgroup "hugetlb_cgroup_test2" "$cgroup_limit2" "$reservation_limit2"
    343
    344  mkdir -p /mnt/huge
    345  mount -t hugetlbfs -o pagesize=${MB}M,size=256M none /mnt/huge
    346
    347  write_hugetlbfs_and_get_usage "hugetlb_cgroup_test1" "$size1" \
    348    "$populate1" "$write1" "/mnt/huge/test1" "$method" "$private" \
    349    "$expect_failure" "$reserve"
    350
    351  hugetlb_difference1=$hugetlb_difference
    352  reserved_difference1=$reserved_difference
    353  reservation_failed1=$reservation_failed
    354  oom_killed1=$oom_killed
    355
    356  local cgroup1_hugetlb_usage=$cgroup_path/hugetlb_cgroup_test1/hugetlb.${MB}MB.$fault_usage_file
    357  local cgroup1_reservation_usage=$cgroup_path/hugetlb_cgroup_test1/hugetlb.${MB}MB.$reservation_usage_file
    358  local cgroup2_hugetlb_usage=$cgroup_path/hugetlb_cgroup_test2/hugetlb.${MB}MB.$fault_usage_file
    359  local cgroup2_reservation_usage=$cgroup_path/hugetlb_cgroup_test2/hugetlb.${MB}MB.$reservation_usage_file
    360
    361  local usage_before_second_write=$(cat $cgroup1_hugetlb_usage)
    362  local reservation_usage_before_second_write=$(cat $cgroup1_reservation_usage)
    363
    364  write_hugetlbfs_and_get_usage "hugetlb_cgroup_test2" "$size2" \
    365    "$populate2" "$write2" "/mnt/huge/test2" "$method" "$private" \
    366    "$expect_failure" "$reserve"
    367
    368  hugetlb_difference2=$hugetlb_difference
    369  reserved_difference2=$reserved_difference
    370  reservation_failed2=$reservation_failed
    371  oom_killed2=$oom_killed
    372
    373  expect_equal "$usage_before_second_write" \
    374    "$(cat $cgroup1_hugetlb_usage)" "Usage changed."
    375  expect_equal "$reservation_usage_before_second_write" \
    376    "$(cat $cgroup1_reservation_usage)" "Reservation usage changed."
    377
    378  cleanup_hugetlb_memory
    379
    380  local final_hugetlb=$(cat $cgroup1_hugetlb_usage)
    381  local final_reservation=$(cat $cgroup1_reservation_usage)
    382
    383  expect_equal "0" "$final_hugetlb" \
    384    "hugetlbt_cgroup_test1 final hugetlb is not zero"
    385  expect_equal "0" "$final_reservation" \
    386    "hugetlbt_cgroup_test1 final reservation is not zero"
    387
    388  local final_hugetlb=$(cat $cgroup2_hugetlb_usage)
    389  local final_reservation=$(cat $cgroup2_reservation_usage)
    390
    391  expect_equal "0" "$final_hugetlb" \
    392    "hugetlb_cgroup_test2 final hugetlb is not zero"
    393  expect_equal "0" "$final_reservation" \
    394    "hugetlb_cgroup_test2 final reservation is not zero"
    395}
    396
    397cleanup
    398
    399for populate in "" "-o"; do
    400  for method in 0 1 2; do
    401    for private in "" "-r"; do
    402      for reserve in "" "-n"; do
    403
    404        # Skip mmap(MAP_HUGETLB | MAP_SHARED). Doesn't seem to be supported.
    405        if [[ "$method" == 1 ]] && [[ "$private" == "" ]]; then
    406          continue
    407        fi
    408
    409        # Skip populated shmem tests. Doesn't seem to be supported.
    410        if [[ "$method" == 2"" ]] && [[ "$populate" == "-o" ]]; then
    411          continue
    412        fi
    413
    414        if [[ "$method" == 2"" ]] && [[ "$reserve" == "-n" ]]; then
    415          continue
    416        fi
    417
    418        cleanup
    419        echo
    420        echo
    421        echo
    422        echo Test normal case.
    423        echo private=$private, populate=$populate, method=$method, reserve=$reserve
    424        run_test 5 "$populate" "" 10 10 10 "$method" "$private" "0" "$reserve"
    425
    426        echo Memory charged to hugtlb=$hugetlb_difference
    427        echo Memory charged to reservation=$reserved_difference
    428
    429        if [[ "$populate" == "-o" ]]; then
    430          expect_equal "$((5 * $MB * 1024 * 1024))" "$hugetlb_difference" \
    431            "Reserved memory charged to hugetlb cgroup."
    432        else
    433          expect_equal "0" "$hugetlb_difference" \
    434            "Reserved memory charged to hugetlb cgroup."
    435        fi
    436
    437        if [[ "$reserve" != "-n" ]] || [[ "$populate" == "-o" ]]; then
    438          expect_equal "$((5 * $MB * 1024 * 1024))" "$reserved_difference" \
    439            "Reserved memory not charged to reservation usage."
    440        else
    441          expect_equal "0" "$reserved_difference" \
    442            "Reserved memory not charged to reservation usage."
    443        fi
    444
    445        echo 'PASS'
    446
    447        cleanup
    448        echo
    449        echo
    450        echo
    451        echo Test normal case with write.
    452        echo private=$private, populate=$populate, method=$method, reserve=$reserve
    453        run_test 5 "$populate" '-w' 5 5 10 "$method" "$private" "0" "$reserve"
    454
    455        echo Memory charged to hugtlb=$hugetlb_difference
    456        echo Memory charged to reservation=$reserved_difference
    457
    458        expect_equal "$((5 * $MB * 1024 * 1024))" "$hugetlb_difference" \
    459          "Reserved memory charged to hugetlb cgroup."
    460
    461        expect_equal "$((5 * $MB * 1024 * 1024))" "$reserved_difference" \
    462          "Reserved memory not charged to reservation usage."
    463
    464        echo 'PASS'
    465
    466        cleanup
    467        continue
    468        echo
    469        echo
    470        echo
    471        echo Test more than reservation case.
    472        echo private=$private, populate=$populate, method=$method, reserve=$reserve
    473
    474        if [ "$reserve" != "-n" ]; then
    475          run_test "5" "$populate" '' "10" "2" "10" "$method" "$private" "1" \
    476            "$reserve"
    477
    478          expect_equal "1" "$reservation_failed" "Reservation succeeded."
    479        fi
    480
    481        echo 'PASS'
    482
    483        cleanup
    484
    485        echo
    486        echo
    487        echo
    488        echo Test more than cgroup limit case.
    489        echo private=$private, populate=$populate, method=$method, reserve=$reserve
    490
    491        # Not sure if shm memory can be cleaned up when the process gets sigbus'd.
    492        if [[ "$method" != 2 ]]; then
    493          run_test 5 "$populate" "-w" 2 10 10 "$method" "$private" "1" "$reserve"
    494
    495          expect_equal "1" "$oom_killed" "Not oom killed."
    496        fi
    497        echo 'PASS'
    498
    499        cleanup
    500
    501        echo
    502        echo
    503        echo
    504        echo Test normal case, multiple cgroups.
    505        echo private=$private, populate=$populate, method=$method, reserve=$reserve
    506        run_multiple_cgroup_test "3" "$populate" "" "10" "10" "5" \
    507          "$populate" "" "10" "10" "10" \
    508          "$method" "$private" "0" "$reserve"
    509
    510        echo Memory charged to hugtlb1=$hugetlb_difference1
    511        echo Memory charged to reservation1=$reserved_difference1
    512        echo Memory charged to hugtlb2=$hugetlb_difference2
    513        echo Memory charged to reservation2=$reserved_difference2
    514
    515        if [[ "$reserve" != "-n" ]] || [[ "$populate" == "-o" ]]; then
    516          expect_equal "3" "$reserved_difference1" \
    517            "Incorrect reservations charged to cgroup 1."
    518
    519          expect_equal "5" "$reserved_difference2" \
    520            "Incorrect reservation charged to cgroup 2."
    521
    522        else
    523          expect_equal "0" "$reserved_difference1" \
    524            "Incorrect reservations charged to cgroup 1."
    525
    526          expect_equal "0" "$reserved_difference2" \
    527            "Incorrect reservation charged to cgroup 2."
    528        fi
    529
    530        if [[ "$populate" == "-o" ]]; then
    531          expect_equal "3" "$hugetlb_difference1" \
    532            "Incorrect hugetlb charged to cgroup 1."
    533
    534          expect_equal "5" "$hugetlb_difference2" \
    535            "Incorrect hugetlb charged to cgroup 2."
    536
    537        else
    538          expect_equal "0" "$hugetlb_difference1" \
    539            "Incorrect hugetlb charged to cgroup 1."
    540
    541          expect_equal "0" "$hugetlb_difference2" \
    542            "Incorrect hugetlb charged to cgroup 2."
    543        fi
    544        echo 'PASS'
    545
    546        cleanup
    547        echo
    548        echo
    549        echo
    550        echo Test normal case with write, multiple cgroups.
    551        echo private=$private, populate=$populate, method=$method, reserve=$reserve
    552        run_multiple_cgroup_test "3" "$populate" "-w" "10" "10" "5" \
    553          "$populate" "-w" "10" "10" "10" \
    554          "$method" "$private" "0" "$reserve"
    555
    556        echo Memory charged to hugtlb1=$hugetlb_difference1
    557        echo Memory charged to reservation1=$reserved_difference1
    558        echo Memory charged to hugtlb2=$hugetlb_difference2
    559        echo Memory charged to reservation2=$reserved_difference2
    560
    561        expect_equal "3" "$hugetlb_difference1" \
    562          "Incorrect hugetlb charged to cgroup 1."
    563
    564        expect_equal "3" "$reserved_difference1" \
    565          "Incorrect reservation charged to cgroup 1."
    566
    567        expect_equal "5" "$hugetlb_difference2" \
    568          "Incorrect hugetlb charged to cgroup 2."
    569
    570        expect_equal "5" "$reserved_difference2" \
    571          "Incorrected reservation charged to cgroup 2."
    572        echo 'PASS'
    573
    574        cleanup
    575
    576      done # reserve
    577    done   # private
    578  done     # populate
    579done       # method
    580
    581if [[ $do_umount ]]; then
    582  umount $cgroup_path
    583  rmdir $cgroup_path
    584fi