1#!/bin/bash
2# MCA error codes validation
3# ./mcaerr_test -a [-b status] [-p processor]
4# ./mcaerr_test -s status [-p processor]
5
6g_testall=0
7g_processor=""
8g_hstat=0x8000000000000000
9g_status=""
10g_tests_dir="$(cd "$(dirname "$0")" && pwd)"
11g_input_dir=$g_tests_dir/../input
12g_tmp_dir=/tmp/mcaerr-tmp
13# save failed MCA error codes during testing
14g_fail_code_log=$g_tests_dir/fail_mcacode_log
15# save undefined MCA error codes during testing
16g_unknown_code_log=$g_tests_dir/unknown_mcacode_log
17# input file for 'mcelog --ascii'
18g_fname=""
19# the expected string parsed from raw MCA error codes.
20g_expect=""
21
22logfile_prepare()
23{
24	if [ -f $g_fail_code_log ]; then
25		: > $g_fail_code_log
26	else
27		touch $g_fail_code_log
28	fi
29
30	if [ -f $g_unknown_code_log ]; then
31		: > $g_unknown_code_log
32	else
33		touch $g_unknown_code_log
34	fi
35}
36
37validate_mca()
38{
39	local mca_prefix="MCA:"
40	local m_ecode=$1
41	local buserr_expect
42
43	# masked F bit in MCA error code
44	if [[ "$1" -ge 0x1000 ]]; then
45		m_ecode=$(($1 & ~0x1000))
46	fi
47
48	g_fname=$(printf "mca-%0x" $1)
49	g_expect=$(cat ./${g_fname}-expect)
50	if [[ "$m_ecode" -ge 0x0800 && "$m_ecode" -lt 0x1000 ]]; then
51		mca_prefix="MCA: BUS error:"
52		buserr_expect="BUS error: $g_expect"
53		echo "expect: $buserr_expect"
54	else
55		echo "expect: $g_expect"
56	fi
57	if mcelog --no-dmi --ascii --file $g_fname | grep "$mca_prefix" | grep -q "$g_expect" ; then
58		return 0
59	else
60		return 1
61	fi
62}
63
64test_all()
65{
66	local m_status
67	local rc
68	local fail_cnt=0
69	local pass_cnt=0
70	local ignore_cnt=0
71
72	if [ ! -d $g_tmp_dir ]; then
73		mkdir $g_tmp_dir
74	fi
75	pushd ./ > /dev/null
76	cd $g_tmp_dir
77	echo "++++++++++Start validating all MCA error codes...++++++++++"
78	for ecode in `seq 0x0000 0x0fff`
79	do
80		m_status=$(($g_hstat | $ecode))
81		printf "m_status=0x%lx\n" $m_status
82		$g_input_dir/GENMCA $m_status "$g_processor"
83		case $? in
84		0)
85			validate_mca $ecode
86			rc=$?
87			if [ $rc -eq 0 ]; then
88				printf "code 0x%x: [PASS]\n" $ecode
89				let "pass_cnt += 1"
90			else
91				printf "code 0x%x: [FAIL]\n" $ecode | tee -a $g_fail_code_log
92				let "fail_cnt += 1"
93			fi
94			;;
95		2)
96			printf "code 0x%x: [IGNORE]\n" $ecode | tee -a $g_unknown_code_log
97			let "ignore_cnt += 1"
98			;;
99		*)
100			echo "It won't go here!"
101			exit 1
102			;;
103		esac
104
105	done
106	echo "++++++++++End validating all MCA error codes++++++++++"
107	printf "PASS: %d, FAIL: %d, IGNORE: %d\n" $pass_cnt $fail_cnt $ignore_cnt
108	popd > /dev/null
109	rm -rf $g_tmp_dir
110}
111
112test_one()
113{
114	local m_ecode
115	local rc
116
117	[ -z "$g_status" ] && usage
118	m_ecode=$(($g_status & 0xffff))
119	$g_input_dir/GENMCA $g_status "$g_processor"
120	case $? in
121	0)
122		validate_mca $m_ecode
123		rc=$?
124		if [ $rc -eq 0 ]; then
125			printf "code 0x%x: [PASS]\n" $m_ecode
126		else
127			printf "code 0x%x: [FAIL]\n" $m_ecode
128		fi
129		echo "Content of the generated input_file lists below:"
130		cat $g_fname
131		rm -rf $g_fname
132		rm -rf ${g_fname}-expect
133		;;
134	2)
135		printf "code %x: [IGNORE]\n" $m_ecode
136		;;
137	*)
138		echo "It won't go here!"
139		exit 1
140		;;
141	esac
142}
143
144usage()
145{
146echo "Usage:"
147echo -e "\t${0##*/} -a [-b status] [-p processor]"
148echo -e "\t${0##*/} -s status [-p processor]"
149echo -e "\t\t-a --- do all MCA error codes validation"
150echo -e "\t\t-b --- 'status' is same as the '-s' option, but the lowest 16 bits are masked."
151echo -e "\t\t-s --- only run MCA error codes test related to 'status' value,"
152echo -e "\t\t       'status' is the 64-bit IA32_MCi_Status value, i.e., 0x8000000000000002."
153echo -e "\t\t-p --- modify 'PROCESSOR' part of the tested input file with 'processor' value,"
154echo -e "\t\t       'processor' must be formated as 'vendor:CPUID', vendor:0 - Intel,"
155echo -e "\t\t       i.e., 0:0x50650, the default value."
156	exit 1
157}
158
159[ "x$1" == "x" ] && usage
160while getopts ":ab:hp:s:" opt
161do
162	case $opt in
163		a) g_testall=1;;
164		b) g_hstat=$(($OPTARG & ~0xffff));;
165		h) usage;;
166		p) g_processor="$OPTARG";;
167		s) g_status=$OPTARG;;
168		*) usage;;
169	esac
170done
171
172if [ "$g_testall" == "1" ]; then
173	logfile_prepare
174	test_all
175else
176	test_one
177fi
178