Commit e966aae1 authored by Pengfei Xu's avatar Pengfei Xu Committed by Aichun Shi
Browse files

selftests: ifs: verify IFS scan test functionality

mainline inclusion
from mainline-v6.11-rc1
commit 3170f7acfba15895844dc2c0f2d2ff6fd77ad2e1
category: feature
bugzilla: https://gitee.com/openeuler/intel-kernel/issues/IASVRQ
CVE: N/A
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=3170f7acfba15895844dc2c0f2d2ff6fd77ad2e1



-------------------------------------

Two selftests are added to verify IFS scan test feature:

1. Perform IFS scan test once on each CPU using all the available image
   files.
2. Perform IFS scan test with the default image on a random cpu for 3
   rounds.

Intel-SIG: commit 3170f7acfba1 selftests: ifs: verify IFS scan test functionality
Backport to support IFS(In Field Scan) SBAF(Structural Based Functional Test at Field)

Reviewed-by: default avatarJithu Joseph <jithu.joseph@intel.com>
Reviewed-by: default avatarKuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
Co-developed-by: default avatarAshok Raj <ashok.raj@intel.com>
Signed-off-by: default avatarAshok Raj <ashok.raj@intel.com>
Signed-off-by: default avatarPengfei Xu <pengfei.xu@intel.com>
Acked-by: default avatarJithu Joseph <jithu.joseph@intel.com>
Signed-off-by: default avatarShuah Khan <skhan@linuxfoundation.org>
[ Aichun Shi: amend commit log ]
Signed-off-by: default avatarAichun Shi <aichun.shi@intel.com>
parent ff871f06
Loading
Loading
Loading
Loading
+189 −1
Original line number Diff line number Diff line
@@ -10,16 +10,25 @@ readonly KSFT_FAIL=1
readonly KSFT_XFAIL=2
readonly KSFT_SKIP=4

readonly CPU_SYSFS="/sys/devices/system/cpu"
readonly CPU_OFFLINE_SYSFS="${CPU_SYSFS}/offline"
readonly IMG_PATH="/lib/firmware/intel/ifs_0"
readonly IFS_SCAN_MODE="0"
readonly IFS_ARRAY_BIST_SCAN_MODE="1"
readonly IFS_PATH="/sys/devices/virtual/misc/intel_ifs"
readonly IFS_SCAN_SYSFS_PATH="${IFS_PATH}_${IFS_SCAN_MODE}"
readonly RUN_TEST="run_test"
readonly STATUS="status"
readonly DETAILS="details"
readonly STATUS_PASS="pass"
readonly PASS="PASS"
readonly FAIL="FAIL"
readonly INFO="INFO"
readonly XFAIL="XFAIL"
readonly SKIP="SKIP"
readonly IFS_NAME="intel_ifs"
readonly ALL="all"
readonly SIBLINGS="siblings"

# Matches arch/x86/include/asm/intel-family.h and
# drivers/platform/x86/intel/ifs/core.c requirement as follows
@@ -28,6 +37,7 @@ readonly EMERALDRAPIDS_X="cf"

readonly INTEL_FAM6="06"

LOOP_TIMES=3
FML=""
MODEL=""
STEPPING=""
@@ -36,11 +46,13 @@ TRUE="true"
FALSE="false"
RESULT=$KSFT_PASS
IMAGE_NAME=""
export INTERVAL_TIME=1
INTERVAL_TIME=1
OFFLINE_CPUS=""
# For IFS cleanup tags
ORIGIN_IFS_LOADED=""
IFS_IMAGE_NEED_RESTORE=$FALSE
IFS_LOG="/tmp/ifs_logs.$$"
RANDOM_CPU=""
DEFAULT_IMG_ID=""

append_log()
@@ -48,6 +60,35 @@ append_log()
	echo -e "$1" | tee -a "$IFS_LOG"
}

online_offline_cpu_list()
{
	local on_off=$1
	local target_cpus=$2
	local cpu=""
	local cpu_start=""
	local cpu_end=""
	local i=""

	if [[ -n "$target_cpus" ]]; then
		for cpu in $(echo "$target_cpus" | tr ',' ' '); do
			if [[ "$cpu" == *"-"* ]]; then
				cpu_start=""
				cpu_end=""
				i=""
				cpu_start=$(echo "$cpu" | cut -d "-" -f 1)
				cpu_end=$(echo "$cpu" | cut -d "-" -f 2)
				for((i=cpu_start;i<=cpu_end;i++)); do
					append_log "[$INFO] echo $on_off > \
${CPU_SYSFS}/cpu${i}/online"
					echo "$on_off" > "$CPU_SYSFS"/cpu"$i"/online
				done
			else
				set_target_cpu "$on_off" "$cpu"
			fi
		done
	fi
}

ifs_scan_result_summary()
{
	local failed_info pass_num skip_num fail_num
@@ -80,6 +121,9 @@ ifs_cleanup()
		mv -f "$IMG_PATH"/"$IMAGE_NAME"_origin "$IMG_PATH"/"$IMAGE_NAME"
	}

	# Restore the CPUs to the state before testing
	[[ -z "$OFFLINE_CPUS" ]] || online_offline_cpu_list "0" "$OFFLINE_CPUS"

	lsmod | grep -q "$IFS_NAME" && [[ "$ORIGIN_IFS_LOADED" == "$FALSE" ]] && {
		echo "[$INFO] modprobe -r $IFS_NAME"
		modprobe -r "$IFS_NAME"
@@ -122,6 +166,23 @@ test_exit()
	ifs_cleanup
}

online_all_cpus()
{
	local off_cpus=""

	OFFLINE_CPUS=$(cat "$CPU_OFFLINE_SYSFS")
	online_offline_cpu_list "1" "$OFFLINE_CPUS"

	off_cpus=$(cat "$CPU_OFFLINE_SYSFS")
	if [[ -z "$off_cpus" ]]; then
		append_log "[$INFO] All CPUs are online."
	else
		append_log "[$XFAIL] There is offline cpu:$off_cpus after online all cpu!"
		RESULT=$KSFT_XFAIL
		ifs_cleanup
	fi
}

get_cpu_fms()
{
	FML=$(grep -m 1 "family" /proc/cpuinfo | awk -F ":" '{printf "%02x",$2;}')
@@ -268,10 +329,135 @@ test_bad_and_origin_ifs_image()
	append_log "[$INFO] Loading invalid IFS image and then loading initial image passed.\n"
}

ifs_test_cpu()
{
	local ifs_mode=$1
	local cpu_num=$2
	local image_id status details ret result result_info

	echo "$cpu_num" > "$IFS_PATH"_"$ifs_mode"/"$RUN_TEST"
	ret=$?

	status=$(cat "${IFS_PATH}_${ifs_mode}/${STATUS}")
	details=$(cat "${IFS_PATH}_${ifs_mode}/${DETAILS}")

	if [[ "$ret" -eq 0 && "$status" == "$STATUS_PASS" ]]; then
		result="$PASS"
	else
		result="$FAIL"
	fi

	cpu_num=$(cat "${CPU_SYSFS}/cpu${cpu_num}/topology/thread_siblings_list")

	# There is no image file for IFS ARRAY BIST scan
	if [[ -e "${IFS_PATH}_${ifs_mode}/current_batch" ]]; then
		image_id=$(cat "${IFS_PATH}_${ifs_mode}/current_batch")
		result_info=$(printf "[%s] ifs_%1d cpu(s):%s, current_batch:0x%02x, \
ret:%2d, status:%s, details:0x%016x" \
			     "$result" "$ifs_mode" "$cpu_num" "$image_id" "$ret" \
			     "$status" "$details")
	else
		result_info=$(printf "[%s] ifs_%1d cpu(s):%s, ret:%2d, status:%s, details:0x%016x" \
			     "$result" "$ifs_mode" "$cpu_num" "$ret" "$status" "$details")
	fi

	append_log "$result_info"
}

ifs_test_cpus()
{
	local cpus_type=$1
	local ifs_mode=$2
	local image_id=$3
	local cpu_max_num=""
	local cpu_num=""

	case "$cpus_type" in
		"$ALL")
			cpu_max_num=$(($(nproc) - 1))
			cpus=$(seq 0 $cpu_max_num)
			;;
		"$SIBLINGS")
			cpus=$(cat ${CPU_SYSFS}/cpu*/topology/thread_siblings_list \
				| sed -e 's/,.*//' \
				| sed -e 's/-.*//' \
				| sort -n \
				| uniq)
			;;
		*)
			test_exit "Invalid cpus_type:$cpus_type" "$KSFT_XFAIL"
			;;
	esac

	for cpu_num in $cpus; do
		ifs_test_cpu "$ifs_mode" "$cpu_num"
	done

	if [[ -z "$image_id" ]]; then
		append_log "[$INFO] ifs_$ifs_mode test $cpus_type cpus completed\n"
	else
		append_log "[$INFO] ifs_$ifs_mode $cpus_type cpus with $CPU_FMS-$image_id.scan \
completed\n"
	fi
}

test_ifs_same_cpu_loop()
{
	local ifs_mode=$1
	local cpu_num=$2
	local loop_times=$3

	append_log "[$INFO] Test ifs mode $ifs_mode on CPU:$cpu_num for $loop_times rounds:"
	[[ "$ifs_mode" == "$IFS_SCAN_MODE" ]] && {
		load_image "$DEFAULT_IMG_ID" ||	return $?
	}
	for (( i=1; i<=loop_times; i++ )); do
		append_log "[$INFO] Loop iteration: $i in total of $loop_times"
		# Only IFS scan needs the interval time
		if [[ "$ifs_mode" == "$IFS_SCAN_MODE" ]]; then
			do_cmd "sleep $INTERVAL_TIME"
		elif [[ "$ifs_mode" == "$IFS_ARRAY_BIST_SCAN_MODE" ]]; then
			true
		else
			test_exit "Invalid ifs_mode:$ifs_mode" "$KSFT_XFAIL"
		fi

		ifs_test_cpu "$ifs_mode" "$cpu_num"
	done
	append_log "[$INFO] $loop_times rounds of ifs_$ifs_mode test on CPU:$cpu_num completed.\n"
}

test_ifs_scan_available_imgs()
{
	local image_ids=""
	local image_id=""

	append_log "[$INFO] Test ifs scan with available images:"
	image_ids=$(find "$IMG_PATH" -maxdepth 1 -name "${CPU_FMS}-[0-9a-fA-F][0-9a-fA-F].scan" \
		    2>/dev/null \
		    | sort \
		    | awk -F "-" '{print $NF}' \
		    | cut -d "." -f 1)

	for image_id in $image_ids; do
		load_image "$image_id" || return $?

		ifs_test_cpus "$SIBLINGS" "$IFS_SCAN_MODE" "$image_id"
		# IFS scan requires time interval for the scan on the same CPU
		do_cmd "sleep $INTERVAL_TIME"
	done
}

prepare_ifs_test_env()
{
	local max_cpu=""

	check_cpu_ifs_support_interval_time

	online_all_cpus
	max_cpu=$(($(nproc) - 1))
	RANDOM_CPU=$(shuf -i 0-$max_cpu -n 1)

	DEFAULT_IMG_ID=$(find $IMG_PATH -maxdepth 1 -name "${CPU_FMS}-[0-9a-fA-F][0-9a-fA-F].scan" \
			 2>/dev/null \
			 | sort \
@@ -290,6 +476,8 @@ test_ifs()
		append_log "[$SKIP] No proper ${IMG_PATH}/${CPU_FMS}-*.scan, skip ifs_0 scan"
	else
		test_bad_and_origin_ifs_image "$DEFAULT_IMG_ID"
		test_ifs_scan_available_imgs
		test_ifs_same_cpu_loop "$IFS_SCAN_MODE" "$RANDOM_CPU" "$LOOP_TIMES"
	fi
}