1#!/bin/bash
2#
3# Software injection based test cases: test cases are triggered via
4# mce-inject tool.
5# Copyright (c) 2010, Intel Corporation
6#
7# This program is free software; you can redistribute it and/or
8# modify it under the terms of the GNU General Public License version
9# 2 as published by the Free Software Foundation.
10#
11# This program is distributed in the hope that it will be useful, but
12# WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14# General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License
17# along with this program; If not, see <http://www.gnu.org/licenses/>.
18#
19# Author: Xudong Hao <xudong.hao@intel.com>
20#
21
22. $ROOT/config/setup.conf
23
24#Guest Image Preparation
25hvm_image_prepare()
26{
27    local image=$1
28    local tmpdir=`mktemp -d`
29    local tmpfile=`mktemp`
30    local offset=`kpartx -l $image | awk '{print $NF*512}'`
31    mount -oloop,offset=$offset $image $tmpdir && echo "mount image to $tmpdir"
32    local g_grub=$tmpdir/boot/grub/grub.conf
33    if [ $? -ne 0 ]; then
34        show "  Mount image failed!"
35        return 1
36    fi
37
38    if ! grep FLAG_CONSOLE $g_grub; then
39        sed -e '/kernel/s/$/ console=ttyS0,115200,8n1 console=tty0/g' \
40            $g_grub > $tmpfile
41        mv -f $tmpfile $g_grub
42        rm -f $tmpfile
43        echo "
44#### FLAG_CONSOLE #### " >> $g_grub
45    fi
46    umount $tmpdir
47    rm -fr $tmpdir
48
49    return 0
50}
51
52create_hvm_guest()
53{
54    local image=$1
55    local originconfig="/etc/xen/xmexample.hvm"
56    local TF=`mktemp`
57    local case_dir=$ROOT/results/$this_case
58    local config=$case_dir/guest_config
59    [ -d $case_dir ] || mkdir $case_dir
60    [ -f $logfile ] || touch $logfile
61    local File=`echo $image|sed "s/\//\\\\\\\\\\//g"`
62    local g_name="`basename $image`_`date +%H%M%S`"
63
64    hvm_image_prepare $image
65
66    while getopts ":u:m:" Option
67    do
68        case $Option in
69            u ) vcpus=$OPTARG;;
70            m ) memory=$OPTARG;;
71            e ) bridge_name=$OPTARG;;
72            * ) ;;
73        esac
74    done
75
76    cp $originconfig $config -f
77
78    if [ -z $image ]; then
79        show "Image file $image does not exist, Please input one valid file"
80        return 1
81    fi
82
83    sed -e "/^disk/s/file:.*,\(hda\)/file:${File},\1/" $config \
84          | sed -e "/^disk/s/phy:.*,\(hda\)/file:${File},\1/" >$TF
85    mv -f $TF $config
86
87    [ -z $memory ] || sed -i "/^memory/s/^.*$/memory = $memory/" $config
88    [ -z $vcpus ] || sed -i "1,/^#vcpus/s/^#vcpus.*$/vcpus=$vcpus/;1d" $config
89    sed -i "/^vif/s/vif/#vif/" $config
90    sed -i "/^name/s/^.*$/name = \"$g_name\"/" $config
91
92    string1=$(ls /dev/pts | sort)
93    xm cr $config
94    [ $? -eq 0 ] && domid=`xm list $g_name | tail -n1 | awk '{print $2}'`
95    if [ -z $domid ]; then
96        show "  Guest can not boot up"
97        return 1
98    fi
99
100    sleep 10
101
102    string2=$(ls /dev/pts | sort)
103
104    get_guest_klog
105    sleep 40
106
107    return 0
108}
109
110get_guest_klog()
111{
112    local case_dir=$ROOT/results/$this_case
113    gklog=$case_dir/gklog
114    [ -d $case_dir ] || mkdir $case_dir
115    [ -f $gklog ] || touch $gklog
116    for fo in $string2; do
117        echo $string1 | grep $fo -wq
118        [ $? -eq 1 ] && num=$fo
119    done
120    cat /dev/pts/$num > $gklog &
121}
122
123mce_inject_trigger()
124{
125    local errtype=$1
126    local append=""
127    while getopts ":d:u:p:" Option
128    do
129        case $Option in
130            d ) domid=$OPTARG;;
131            u ) cpu=$OPTARG;;
132            p ) pageaddr=$OPTARG;;
133            * ) ;;
134        esac
135    done
136
137    [ -z $domid ] || append=$append" -d $domid"
138    [ -z $cpu ] || append=$append" -c $cpu"
139    [ -z $pageaddr ] || append=$append" -p $pageaddr"
140
141    [ -f $ROOT/tools/xen-mceinj ]
142    if [ $? -eq 0 ]; then
143        xm dmesg -c
144        $ROOT/tools/xen-mceinj -t $errtype $append
145        if [ $? -ne 0 ]; then
146            show "  Failed: Maybe the memory addr is out of range. \
147                      Please check whether used xen-mceinj tool correctlly"
148            return 1
149        fi
150    else
151        show "  Failed: please compile xen-mce inject tool firstly"
152        return 1
153    fi
154    return 0
155}
156
157xen_verify()
158{
159    local case_dir=$ROOT/results/$this_case
160    local xenlog=$case_dir/xenlog
161    [ -d $case_dir ] || mkdir $case_dir
162    [ -f $xenlog ] || touch $xenlog
163    xm dmesg > $xenlog
164    grep "Error is successfully recovered" $xenlog > /dev/null
165    if [ $? -eq 0 ]; then
166        show "  Passed: Xen handle this MCE error successfully"
167    else
168        show "  Failed: Xen does not handle MCE error correctly !!"
169        return 1
170    fi
171    return 0
172}
173
174guest_verify()
175{
176    grep "kernel page recovery" $gklog > /dev/null
177    if [ $? -eq 0 ]; then
178        show "  Passed: Guest recive MCE error and solved correctly"
179    else
180        show "  Failed: Guest fail to solve MCE error"
181        return 1
182    fi
183    return 0
184}
185
186mcelog_verify()
187{
188    local err_type=$1
189    local ret=0
190    local case_dir=$ROOT/results/$this_case
191    local mcelog=$case_dir/mcelog
192    [ -d $case_dir ] || mkdir $case_dir
193    [ -f $mcelog ] || touch $mcelog
194    mcelog > $mcelog
195    if [ -z $mcelog ]; then
196        show "  Failed: MCELOG does not catch anything"
197        return 1
198    else
199        if [ $err_type -eq 0 ]; then
200            grep "MEMORY CONTROLLER MS_CHANNELunspecified_ERR" $mcelog \
201                > /dev/null
202            ret=$?
203        elif [ $err_type -eq 1 ]; then
204            grep "Generic CACHE Level-2 Eviction Error" $mcelog > /dev/null
205            ret=$?
206        elif [ $err_type -eq 2 ]; then
207            grep "Data CACHE Level-2 Data-Read Error" $mcelog > /dev/null
208            ret=$?
209        fi
210
211        if [ $ret -eq 0 ]; then
212            show "  Passed: MCElog catch a correct error"
213        else
214            show "  Failed: MCE log catch a incorrect error !!"
215            return 1
216        fi
217    fi
218
219    return 0
220}
221
222function des_guest()
223{
224    xm des $domid
225}
226
227function clean_env()
228{
229    [ -d $ROOT/results ] || mkdir $ROOT/results
230    # clean logs and results of last test for this case
231    rm -fr $ROOT/results/$this_case/*
232}
233
234function show()
235{
236    local case_dir=$ROOT/results/$this_case
237    local logfile=$case_dir/testlog
238    [ -d $case_dir ] || mkdir $case_dir
239    [ -f $logfile ] || touch $logfile
240    echo -e $* | tee -a $logfile > /dev/null
241}
242
243function gen_result()
244{
245    local ret=$1
246    local case_dir=$ROOT/results/$this_case
247    local result=$case_dir/result
248    [ -d $case_dir ] || mkdir $case_dir
249    [ -f $result ] || touch $result
250
251    if [ $ret -eq 0 ]; then
252        echo "PASSED" > $result
253    elif [ $ret -eq 1 ]; then
254        echo "FAILED" > $result
255        echo "   Please check testlog for details!!! " >> $result
256    else
257        echo "NORESULT" > $result
258        echo "   Please check testlog for details!!! " >> $result
259    fi
260}
261