diff options
author | Jiajia Zheng <jiajia.zheng@intel.com> | 2010-02-04 16:31:08 +0800 |
---|---|---|
committer | Huang Ying <ying.huang@intel.com> | 2010-02-04 16:31:08 +0800 |
commit | d1be787452998a3e7c58590ff07acc2437e90fe3 (patch) | |
tree | 6d75ce0be565888cd038130f6b3919ae90e3da24 | |
parent | 8a01959454db5dfd22d88ee1bd3d6e5023d2a8da (diff) | |
download | mce-test-d1be787452998a3e7c58590ff07acc2437e90fe3.tar.gz |
Add KVM RAS test suite
This patch is to add KVM RAS test suite into mce-test, which is a
collection of test scripts for testing the Linux kernel MCE processing
features in KVM guest system.
Signed-off-by: Jiajia Zheng <jiajia.zheng@intel.com>
Signed-off-by: Huang Ying <ying.huang@intel.com>
-rw-r--r-- | kvm/README | 62 | ||||
-rw-r--r-- | kvm/guest/guest_run.sh | 36 | ||||
-rw-r--r-- | kvm/host/SRAO | 4 | ||||
-rw-r--r-- | kvm/host/guest_init | 37 | ||||
-rw-r--r-- | kvm/host/host_run.sh | 282 | ||||
-rw-r--r-- | tools/simple_process/simple_process.c | 3 |
6 files changed, 422 insertions, 2 deletions
diff --git a/kvm/README b/kvm/README new file mode 100644 index 0000000..c625b2d --- /dev/null +++ b/kvm/README @@ -0,0 +1,62 @@ +KVM RAS Test Suite +================== +The KVM RAS Test Suite is a collection of test scripts for testing the +Linux kernel MCE processing features in KVM guest system. + +Jan 26th, 2010 + +Jiajia Zheng + + +In the Package +---------------- + +Here is a short description of what is included in the package + +host/* + Contains host test scripts, which drive test procedure on host system. +guest/* + Contains guest test scripts, which drive test procedure on guest system. + +Dependencies +---------------- + +KVM RAS Test Suite has following dependencies on kernel and other tools: + +* Linux Kernel: + Version 2.6.32 or newer, with MCA high level handlers enabled. + +* page-types: + A tool to query page types, which is accompanied with Linux kernel + source (2.6.32 or newer, $KERNEL_SRC/Documentation/vm/page-types.c). + +* simple_process: + A process constantly access the allocated memeory. (../tools/simple_process) + +Installation +--------------- +1. Build host kernel with + CONFIG_KVM=y + CONFIG_KVM_INTEL=y +2. Create a testing dirctory on host system and put the host test scripts + and test tool (page-types) into it. + By default, the testing directory is /test. +3. Use ssh-keygen to generate public and privite keys, and copy them into the + testing directory on host system. +4. Mount guest image +5. Create a testing dirctory on guest system and copy guest test script and + tools (page-types, simple_process) into it. + By default, the testing directory is /test. +6. Use qemu to start guest system, install page-types and simple_process on + guest system. + gcc -o page-types page-types.c + cd simple_process + make + +Start Testing +--------------- +Run testing by + ./host_run.sh <option> <argument> +You can get the help information by + ./host_run.sh -h + diff --git a/kvm/guest/guest_run.sh b/kvm/guest/guest_run.sh new file mode 100644 index 0000000..384e1f4 --- /dev/null +++ b/kvm/guest/guest_run.sh @@ -0,0 +1,36 @@ +#!/bin/bash +# +# Test script for KVM RAS +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public +# License as published by the Free Software Foundation; version +# 2. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should find a copy of v2 of the GNU General Public License somewhere +# on your Linux system; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# Copyright (C) 2010, Intel Corp. +# Author: Jiajia Zheng <jiajia.zheng@intel.com> +# + +GUEST_DIR=`dirname $0` +guest_page=$GUEST_DIR/guest_page +guest_tmp=$GUEST_DIR/guest_tmp + +killall simple_process +$GUEST_DIR/simple_process/simple_process > /dev/null & + +$GUEST_DIR/page-types/page-types -p `pidof simple_process` -LN -b anon > $guest_page +if [ -s $guest_page ]; then + ADDR_KLOG=`awk '$2 != "offset" {print "0x"$2}' $guest_page | sed -n -e '1p'` + ADDR=`echo $ADDR_KLOG"000"` + echo "guest physical address is $ADDR" > $guest_tmp +fi + diff --git a/kvm/host/SRAO b/kvm/host/SRAO new file mode 100644 index 0000000..cecffa1 --- /dev/null +++ b/kvm/host/SRAO @@ -0,0 +1,4 @@ +CPU 0 BANK 2 +STATUS UNCORRECTED SRAO 0x17a +MCGSTATUS MCIP RIPV +MISC 0x8c diff --git a/kvm/host/guest_init b/kvm/host/guest_init new file mode 100644 index 0000000..b16d2b4 --- /dev/null +++ b/kvm/host/guest_init @@ -0,0 +1,37 @@ +#!/bin/bash + +# Source function library. +. /etc/init.d/functions + + +RETVAL=0 + +start() { + + touch /root/jobdone + mount -t debugfs null /sys/kernel/debug + echo 1 > /sys/kernel/debug/mce/fake_ser_p + echo 1 > /proc/sys/vm/memory_failure_early_kill + sh GUESTRUN & + return "$RETVAL" +} + +stop() { + return "$RETVAL" +} + +# See how we were called. +case "$1" in + start) + start + ;; + stop) + stop + ;; + *) + echo $"Usage: $0 {start|stop}" + exit 3 +esac + +exit "$RETVAL" + diff --git a/kvm/host/host_run.sh b/kvm/host/host_run.sh new file mode 100644 index 0000000..10884d0 --- /dev/null +++ b/kvm/host/host_run.sh @@ -0,0 +1,282 @@ +#!/bin/bash +# +# Test script for KVM RAS +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public +# License as published by the Free Software Foundation; version +# 2. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should find a copy of v2 of the GNU General Public License somewhere +# on your Linux system; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# Copyright (C) 2010, Intel Corp. +# Author: Jiajia Zheng <jiajia.zheng@intel.com> +# + +image="" +mce_inject_file="" + +HOST_DIR="/test" +GUEST_DIR="/test" +host_key_pub="$HOST_DIR/id_rsa.pub" +host_key_priv="$HOST_DIR/id_rsa" +early_kill="1" + +kernel="" +initrd="" +root="" + +usage() +{ + echo "Usage: ./host_run.sh [-options] [arguments]" + echo "================Below are the must have options===============" + echo -e "\t-i image\t: guest image" + echo -e "\t-f mcefile\t: which mce data file to inject" + echo "================Below are the optional options================" + echo -e "\t-d hostdir\t: where you put the test scripts on host system" + echo -e "\t\t\tBy default, hostdir is set to $HOST_DIR" + echo -e "\t-g guestdir\t: where you put the test scripts on guest system" + echo -e "\t\t\tBy default, hostdir is set to $GUEST_DIR" + echo -e "\t-b pubkey\t: host public key" + echo -e "\t\t\tBy default, host public key is $host_key_pub" + echo -e "\t-p privkey\t: host privite key" + echo -e "\t\t\tBy default, host privite key is $host_key_priv" + echo -e "\t-o offset\t: guest image offset (optional) " + echo -e "\t\t\tBy default, offset is calculated by kpartx " + echo -e "\t-l latekill\t: disable early kill in guest system" + echo -e "\t\t\tBy default, earlykill is enabled " + echo "============If you want to specify the guest kernel===========" + echo "============please set below options all together=============" + echo -e "\t-k kernel\t: guest kernel" + echo -e "\t-n initrd\t: guest initrd" + echo -e "\t-r root\t\t: guest root partition" + exit 0 +} + +while getopts ":i:f:d:g:o:b:p:k:n:r:h:l" option +do + case $option in + i) image=$OPTARG; offset=`kpartx -l $image | awk '{print $NF*512}'`;; + f) mce_inject_file=$OPTARG;; + d) HOST_DIR=$OPTARG; host_key_pub=$HOST_DIR/id_rsa.pub; host_key_priv=$HOST_DIR/id_rsa;; + g) GUEST_DIR=$OPTARG;; + b) host_key_pub=$OPTARG;; + p) host_key_priv=$OPTARG;; + o) offset=$OPTARG;; + l) early_kill="0";; + k) kernel=$OPTARG;; + n) initrd=$OPTARG;; + r) root=$OPTARG;; + h) usage;; + *) echo "invalid option!"; usage;; + esac +done + + +guest_script=$GUEST_DIR/guest_run.sh +guest_tmp=$GUEST_DIR/guest_tmp +guest_page=$GUEST_DIR/guest_page +GUEST_PHY="" + +guest_init=$HOST_DIR/guest_init +host_start=$HOST_DIR/host_start +pid_file=$HOST_DIR/pid_file +monitor_console="" +serial_console="" +monitor_console_output=$HOST_DIR/monitor_console_output +serial_console_output=$HOST_DIR/serial_console_output +host_tmp=$HOST_DIR/host_tmp +mce_inject_data=$HOST_DIR/mce_inject_data + + +invalid() +{ + echo $1 + echo "Try \`./host_run.sh -h\` for more information." + exit 0 +} + +check_env() +{ + [ -z $image ] && invalid "please input the guest image!" + [ ! -e $image ] && invalid "guest image $image does not exist!" + [ -z $mce_inject_file ] && invalid "please input the mce data file!" + [ ! -e $mce_inject_file ] && invalid "mce data file $mce_inject_file does not exist!" + + [ ! -e $host_key_pub ] && invalid "host public key does not exist!" + [ ! -e $host_key_priv ] && invalid "host privite key does not exist!" + chmod 600 $host_key_pub + chmod 600 $host_key_priv +} + +#Guest Image Preparation +image_prepare() +{ + mnt=`mktemp -d` + mount -oloop,offset=$offset $image $mnt && echo "mount image to $mnt " + if [ $? -ne 0 ]; then + echo "mount image failed!" + return 1 + fi + + [ ! -e $mnt$guest_script ] && umount $mnt && invalid "Invalid guest directory!" + rm -f $mnt/etc/rc3.d/S99kvm_ras + rm -f $mnt$guest_tmp $mnt$guest_page + + if [ ! -d $mnt/root/.ssh ]; then + mkdir $mnt/root/.ssh + chmod 700 $mnt/root/.ssh + fi + cat $host_key_pub >> $mnt/root/.ssh/authorized_keys + kvm_ras=/etc/init.d/kvm_ras + sed "s#EARLYKILL#$early_kill#g" $guest_init | sed "s#GUESTRUN#$guest_script#g" > $mnt$kvm_ras + chmod a+x $mnt$kvm_ras + ln -s $kvm_ras $mnt/etc/rc3.d/S99kvm_ras + sleep 2 + umount $mnt + sleep 2 + rm -rf $mnt + return 0 +} + +#Start guest system +start_guest() +{ + local i + if [ ! -z $kernel ]; then + if [ ! -z $initrd ]; then + if [ ! -z $root ]; then + append="root=$root ro loglevel=8 mce=3 console=ttyS0,115200n8 console=tty0" + qemu-system-x86_64 -hda $image -kernel $kernel -initrd $initrd --append "$append" \ + -net nic,model=rtl8139 -net user,hostfwd=tcp::5555-:22 -monitor pty -serial pty \ + -pidfile $pid_file > $host_start 2>&1 & + sleep 5 + else + invalid "please specify the guest root partition!" + fi + else + invalid "please specify the guest initrd!" + fi + else + echo "Start the default kernel on guest system" + qemu-system-x86_64 -hda $image -net nic,model=rtl8139 -net user,hostfwd=tcp::5555-:22 \ + -monitor pty -serial pty -pidfile $pid_file > $host_start 2>&1 & + sleep 5 + fi + monitor_console=`awk '{print $NF}' $host_start | sed -n -e '1p'` + serial_console=`awk '{print $NF}' $host_start | sed -n -e '2p'` + QUME_PID=`cat $pid_file` + echo "monitor console is $monitor_console" + echo "serial console is $serial_console" + echo "Waiting for guest system start up..." +} + +check_guest_alive() +{ + for i in 1 2 3 4 5 6 7 8 9 + do + sleep 10 + ssh -i $host_key_priv localhost -p 5555 echo "" > /dev/null 2>&1 + if [ $? -eq 0 ]; then + return 0 + else + echo "Waiting..." + fi + done + return 1 +} + +addr_translate() +{ + #Get Guest physical address + scp -i $host_key_priv -P 5555 localhost:$guest_tmp $guest_tmp > /dev/null 2>&1 + if [ $? -ne 0 ]; then + echo "Failed to get Guest physical address, quit testing!" + exit 0 + fi + sleep 2 + GUEST_PHY=`awk '{print $NF}' $guest_tmp` + echo "Guest physical address is $GUEST_PHY" + sleep 2 + + #Get Host virtual address + echo p2v $GUEST_PHY > $monitor_console + cat $monitor_console > $monitor_console_output & + sleep 5 + HOST_VIRT=`awk '/address/{print $NF}' $monitor_console_output |cut -b 3-11` + echo "Host virtual address is $HOST_VIRT" + + #Get Host physical address + page-types/page-types -p $QUME_PID -LN -b anon | grep $HOST_VIRT > $host_tmp + sleep 5 + ADDR=`cat $host_tmp | awk '{print "0x"$2"000"}' ` + echo "Host physical address is $ADDR" +} + +error_inj() +{ + #Inject SRAO error + cat $mce_inject_file > $mce_inject_data + echo "ADDR $ADDR" >> $mce_inject_data + mce-inject $mce_inject_data +} + + +get_guest_klog() +{ + cat $serial_console > $serial_console_output & +} + +check_guest_klog() +{ + GUEST_PHY_KLOG=`echo $GUEST_PHY | sed 's/000$//'` + echo "Guest physical klog address is $GUEST_PHY_KLOG" + cat $serial_console_output | grep "MCE $GUEST_PHY_KLOG" + if [ $? -ne 0 ]; then + return 1 + fi + return 0 +} + + + +check_env +image_prepare +if [ $? -ne 0 ]; then + echo "Mount Guest image failed, quit testing!" +else + start_guest + get_guest_klog + check_guest_alive + if [ $? -ne 0 ]; then + echo "Start Guest system failed, quit testing!" + else + sleep 5 + addr_translate + error_inj + sleep 5 + check_guest_klog + if [ $? -ne 0 ]; then + echo "FAIL: Did not get expected log!" + exit 0 + else + echo "PASS: Inject error into guest!" + fi + sleep 10 + check_guest_alive + if [ $? -ne 0 ]; then + echo "FAIL: Guest System could have died!" + else + echo "PASS: Guest System alive!" + fi + fi +fi + +rm -f $host_start $monitor_console_output $serail_console_output $host_tmp $pid_file $mce_inject_data diff --git a/tools/simple_process/simple_process.c b/tools/simple_process/simple_process.c index 666d543..b6d3c4c 100644 --- a/tools/simple_process/simple_process.c +++ b/tools/simple_process/simple_process.c @@ -6,11 +6,10 @@ int main(void) { void *p = malloc(128); - memset(p, 0, 128); printf("allocating 128 bytes of memory\n"); while (1) { - sleep(1); + memset(p, 0, 128); } return 0; } |