|
| 1 | +#!/bin/bash |
| 2 | +# SPDX-License-Identifier: GPL-2.0 |
| 3 | +# |
| 4 | +# Test the functionality of the Intel IFS(In Field Scan) driver. |
| 5 | +# |
| 6 | + |
| 7 | +# Matched with kselftest framework: tools/testing/selftests/kselftest.h |
| 8 | +readonly KSFT_PASS=0 |
| 9 | +readonly KSFT_FAIL=1 |
| 10 | +readonly KSFT_XFAIL=2 |
| 11 | +readonly KSFT_SKIP=4 |
| 12 | + |
| 13 | +readonly IFS_SCAN_MODE="0" |
| 14 | +readonly IFS_PATH="/sys/devices/virtual/misc/intel_ifs" |
| 15 | +readonly IFS_SCAN_SYSFS_PATH="${IFS_PATH}_${IFS_SCAN_MODE}" |
| 16 | +readonly PASS="PASS" |
| 17 | +readonly FAIL="FAIL" |
| 18 | +readonly INFO="INFO" |
| 19 | +readonly XFAIL="XFAIL" |
| 20 | +readonly SKIP="SKIP" |
| 21 | +readonly IFS_NAME="intel_ifs" |
| 22 | + |
| 23 | +# Matches arch/x86/include/asm/intel-family.h and |
| 24 | +# drivers/platform/x86/intel/ifs/core.c requirement as follows |
| 25 | +readonly SAPPHIRERAPIDS_X="8f" |
| 26 | +readonly EMERALDRAPIDS_X="cf" |
| 27 | + |
| 28 | +readonly INTEL_FAM6="06" |
| 29 | + |
| 30 | +FML="" |
| 31 | +MODEL="" |
| 32 | + |
| 33 | +TRUE="true" |
| 34 | +FALSE="false" |
| 35 | +RESULT=$KSFT_PASS |
| 36 | +export INTERVAL_TIME=1 |
| 37 | +# For IFS cleanup tags |
| 38 | +ORIGIN_IFS_LOADED="" |
| 39 | +IFS_LOG="/tmp/ifs_logs.$$" |
| 40 | + |
| 41 | +append_log() |
| 42 | +{ |
| 43 | + echo -e "$1" | tee -a "$IFS_LOG" |
| 44 | +} |
| 45 | + |
| 46 | +ifs_scan_result_summary() |
| 47 | +{ |
| 48 | + local failed_info pass_num skip_num fail_num |
| 49 | + |
| 50 | + if [[ -e "$IFS_LOG" ]]; then |
| 51 | + failed_info=$(grep ^"\[${FAIL}\]" "$IFS_LOG") |
| 52 | + fail_num=$(grep -c ^"\[${FAIL}\]" "$IFS_LOG") |
| 53 | + skip_num=$(grep -c ^"\[${SKIP}\]" "$IFS_LOG") |
| 54 | + pass_num=$(grep -c ^"\[${PASS}\]" "$IFS_LOG") |
| 55 | + |
| 56 | + if [[ "$fail_num" -ne 0 ]]; then |
| 57 | + RESULT=$KSFT_FAIL |
| 58 | + echo "[$INFO] IFS test failure summary:" |
| 59 | + echo "$failed_info" |
| 60 | + elif [[ "$skip_num" -ne 0 ]]; then |
| 61 | + RESULT=$KSFT_SKIP |
| 62 | + fi |
| 63 | + echo "[$INFO] IFS test pass:$pass_num, skip:$skip_num, fail:$fail_num" |
| 64 | + else |
| 65 | + echo "[$INFO] No file $IFS_LOG for IFS scan summary" |
| 66 | + fi |
| 67 | +} |
| 68 | + |
| 69 | +ifs_cleanup() |
| 70 | +{ |
| 71 | + lsmod | grep -q "$IFS_NAME" && [[ "$ORIGIN_IFS_LOADED" == "$FALSE" ]] && { |
| 72 | + echo "[$INFO] modprobe -r $IFS_NAME" |
| 73 | + modprobe -r "$IFS_NAME" |
| 74 | + } |
| 75 | + |
| 76 | + ifs_scan_result_summary |
| 77 | + [[ -e "$IFS_LOG" ]] && rm -rf "$IFS_LOG" |
| 78 | + |
| 79 | + echo "[RESULT] IFS test exit with $RESULT" |
| 80 | + exit "$RESULT" |
| 81 | +} |
| 82 | + |
| 83 | +test_exit() |
| 84 | +{ |
| 85 | + local info=$1 |
| 86 | + RESULT=$2 |
| 87 | + |
| 88 | + declare -A EXIT_MAP |
| 89 | + EXIT_MAP[$KSFT_PASS]=$PASS |
| 90 | + EXIT_MAP[$KSFT_FAIL]=$FAIL |
| 91 | + EXIT_MAP[$KSFT_XFAIL]=$XFAIL |
| 92 | + EXIT_MAP[$KSFT_SKIP]=$SKIP |
| 93 | + |
| 94 | + append_log "[${EXIT_MAP[$RESULT]}] $info" |
| 95 | + ifs_cleanup |
| 96 | +} |
| 97 | + |
| 98 | +get_cpu_fms() |
| 99 | +{ |
| 100 | + FML=$(grep -m 1 "family" /proc/cpuinfo | awk -F ":" '{printf "%02x",$2;}') |
| 101 | + MODEL=$(grep -m 1 "model" /proc/cpuinfo | awk -F ":" '{printf "%02x",$2;}') |
| 102 | +} |
| 103 | + |
| 104 | +check_cpu_ifs_support_interval_time() |
| 105 | +{ |
| 106 | + get_cpu_fms |
| 107 | + |
| 108 | + if [[ "$FML" != "$INTEL_FAM6" ]]; then |
| 109 | + test_exit "CPU family:$FML does not support IFS" "$KSFT_SKIP" |
| 110 | + fi |
| 111 | + |
| 112 | + # Ucode has time interval requirement for IFS scan on same CPU as follows: |
| 113 | + case $MODEL in |
| 114 | + "$SAPPHIRERAPIDS_X") |
| 115 | + INTERVAL_TIME=180; |
| 116 | + ;; |
| 117 | + "$EMERALDRAPIDS_X") |
| 118 | + INTERVAL_TIME=30; |
| 119 | + ;; |
| 120 | + *) |
| 121 | + # Set default interval time for other platforms |
| 122 | + INTERVAL_TIME=1; |
| 123 | + append_log "[$INFO] CPU FML:$FML model:0x$MODEL, default: 1s interval time" |
| 124 | + ;; |
| 125 | + esac |
| 126 | +} |
| 127 | + |
| 128 | +check_ifs_loaded() |
| 129 | +{ |
| 130 | + local ifs_info="" |
| 131 | + |
| 132 | + ifs_info=$(lsmod | grep "$IFS_NAME") |
| 133 | + if [[ -z "$ifs_info" ]]; then |
| 134 | + append_log "[$INFO] modprobe $IFS_NAME" |
| 135 | + modprobe "$IFS_NAME" || { |
| 136 | + test_exit "Check if CONFIG_INTEL_IFS is set to m or \ |
| 137 | +platform doesn't support ifs" "$KSFT_SKIP" |
| 138 | + } |
| 139 | + ifs_info=$(lsmod | grep "$IFS_NAME") |
| 140 | + [[ -n "$ifs_info" ]] || test_exit "No ifs module listed by lsmod" "$KSFT_FAIL" |
| 141 | + fi |
| 142 | +} |
| 143 | + |
| 144 | +test_ifs_scan_entry() |
| 145 | +{ |
| 146 | + local ifs_info="" |
| 147 | + |
| 148 | + ifs_info=$(lsmod | grep "$IFS_NAME") |
| 149 | + |
| 150 | + if [[ -z "$ifs_info" ]]; then |
| 151 | + ORIGIN_IFS_LOADED="$FALSE" |
| 152 | + check_ifs_loaded |
| 153 | + else |
| 154 | + ORIGIN_IFS_LOADED="$TRUE" |
| 155 | + append_log "[$INFO] Module $IFS_NAME is already loaded" |
| 156 | + fi |
| 157 | + |
| 158 | + if [[ -d "$IFS_SCAN_SYSFS_PATH" ]]; then |
| 159 | + append_log "[$PASS] IFS sysfs $IFS_SCAN_SYSFS_PATH entry is created\n" |
| 160 | + else |
| 161 | + test_exit "No sysfs entry in $IFS_SCAN_SYSFS_PATH" "$KSFT_FAIL" |
| 162 | + fi |
| 163 | +} |
| 164 | + |
| 165 | +prepare_ifs_test_env() |
| 166 | +{ |
| 167 | + check_cpu_ifs_support_interval_time |
| 168 | +} |
| 169 | + |
| 170 | +test_ifs() |
| 171 | +{ |
| 172 | + prepare_ifs_test_env |
| 173 | + |
| 174 | + test_ifs_scan_entry |
| 175 | +} |
| 176 | + |
| 177 | +trap ifs_cleanup SIGTERM SIGINT |
| 178 | +test_ifs |
| 179 | +ifs_cleanup |
0 commit comments