blob: fe97aed8685152fd52068ed453217e61958c8ff3 [file] [log] [blame]
#!/bin/bash
. ../../../lib/mce.sh
INJ_TYPE=0x00000008
APEI_IF=""
PFA_BIN=""
EDAC_TYPE=""
invalid()
{
echo $*
exit 1
}
apei_inj()
{
echo $INJ_TYPE > $APEI_IF/error_type
echo $1 > $APEI_IF/param1
echo 0xfffffffffffff000 > $APEI_IF/param2
echo 1 > $APEI_IF/error_inject
}
usage()
{
cat <<-EOF
usage: ${0##*/} [PFA program] [trigger interval time]
example: ${0##*/} ./pfa 10
EOF
}
main()
{
if [ X"$1" = X -o X"$2" = X ]
then
usage
exit 0
fi
PFA_BIN=$1
check_debugfs
APEI_IF=`cat /proc/mounts | grep debugfs | cut -d ' ' -f2 | head -1`/apei/einj
#if einj is not builtin, just insmod it
if [ ! -d $APEI_IF ]; then
#if einj is a module, it is ensured to have been loaded
modprobe einj param_extension=1 > /dev/null 2>&1
[ $? -eq 0 ] || invalid "module einj isn't supported?"
fi
[ -f $APEI_IF/param1 ] ||
invalid "no BIOS extension support for APEI on this platform"
#check if the platform supports Correctable Memory Error injection
cat $APEI_IF/available_error_type | grep -q $INJ_TYPE
[ $? -ne 0 ] &&
invalid "Necessary Error Injection for PFA is not supported on this platform"
# remove possible EDAC module, otherwise, the error information will be ate
# by EDAC module and mcelog will not get it.
# By now, only i7core_edac and sb_edac hook into the mcelog kernel buffer
cat /proc/modules | grep -q i7core_edac
if [ $? -eq 0 ]; then
EDAC_TYPE="i7core_edac"
else
cat /proc/modules | grep -q sb_edac
[ $? -eq 0 ] && EDAC_TYPE="sb_edac"
fi
rmmod $EDAC_TYPE >/dev/null 2>&1
killall $PFA_BIN > /dev/null 2>&1
$PFA_BIN | tee log &
#wait to flush stdout into log
sleep 1
addr=`cat log |cut -d' ' -f8|tail -1`
last_addr=$addr
start=`date +%s`
while :
do
echo inject address = $addr
apei_inj $addr
sleep $2
addr=`cat log |cut -d' ' -f8|tail -1`
end=`date +%s`
timeout=`expr $end - $start`
if [ X"$last_addr" != X"$addr" ]
then
break
# assume it is enough to trigger PFA in 5 minutes
elif [ $timeout -ge 300 ]; then
invalid "Timeout! PFA is not triggered"
fi
done
}
cleanup()
{
rm -f trigger log
modprobe $EDAC_TYPE >/dev/null 2>&1
}
trap "cleanup" 0
main "$@"