diff options
author | Wen Jin <wenx.jin@intel.com> | 2015-12-24 11:05:23 +0800 |
---|---|---|
committer | Andi Kleen <ak@linux.intel.com> | 2015-12-25 19:39:09 -0800 |
commit | f3df4b7daec9c8535b6407e1328572fd0af3022b (patch) | |
tree | e6cf84e8ae0e27b63949bfa51bf63fee62ff192e | |
parent | ac82804edef3137aa153838c038d35f7e80f50f9 (diff) | |
download | mce-test-f3df4b7daec9c8535b6407e1328572fd0af3022b.tar.gz |
Support SRAR error injection in QEMU/KVM
This patch is used to test SRAR error recovery in QEMU/KVM.
Meanwhile. It uses EINJ to substitute mce-inject as injection
tool to ensure error happended in QEMU context.
Minor update by Gong.
Signed-off-by: Wen Jin <wenx.jin@intel.com>
Signed-off-by: Chen, Gong <gong.chen@linux.intel.com>
Signed-off-by: Andi Kleen <ak@linux.intel.com>
-rw-r--r-- | cases/function/kvm/README | 207 | ||||
-rw-r--r--[-rwxr-xr-x] | cases/function/kvm/guest/guest_run_simple.sh (renamed from cases/function/kvm/guest/guest_run.sh) | 15 | ||||
-rw-r--r-- | cases/function/kvm/guest/guest_run_victim.sh | 38 | ||||
-rwxr-xr-x | cases/function/kvm/host/host_run.sh | 353 | ||||
-rw-r--r-- | cases/function/kvm/patches/p2v.patch | 94 | ||||
-rw-r--r-- | tools/simple_process/simple_process.c | 17 |
6 files changed, 485 insertions, 239 deletions
diff --git a/cases/function/kvm/README b/cases/function/kvm/README index d79fb52..938bbbc 100644 --- a/cases/function/kvm/README +++ b/cases/function/kvm/README @@ -1,12 +1,10 @@ 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 +The KVM RAS Test Suite is a collection of test scripts for testing +Linux kernel MCE processing features in QEMU/KVM. +Jiajia Zheng, Jan 26th, 2010 +Updated by Wen Jin <wenx.jin@intel.com>, 2015-12-08 In the Package ---------------- @@ -25,28 +23,49 @@ 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. + To test LMCE(Local MCE), kernel 4.3+ is needed. * mce-inject - A tool to inject mce error into kernel + A tool to inject MCE error(spoof) into kernel. + +* mcelog + A tool that must be installed on both host and guest system to collect + logs related to MCE error. Ensure mcelog always running in daemon mode + on guest system after booting up. Please always use latest version. + + You can get it from here: + git://git.kernel.org/pub/scm/utils/cpu/mce/mcelog.git + https://git.kernel.org/pub/scm/utils/cpu/mce/mcelog.git * 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). + A tool to query page types, which is accompanied by Linux kernel + source (2.6.32+, $KERNEL_SRC/Documentation/vm/page-types.c or + 3.3+ $KERNEL_SRC/tools/vm/page-types.c). * simple_process: - A process constantly access the allocated memeory. (../tools/simple_process) + A process constantly access the allocated memeory. + Located under mce-test/tools/simple_process/. + +* victim + Play a role like *simple_process* but more powerful. + +* qemu-img: + QEMU disk image utility. + +* qemu-nbd: + A tool to mount QEMU disk image(i.e. qcow2) with NBD protocol. * kpartx: - A tool to list partition mappings from partition tables + A tool to list partition mappings from partition tables. * (optionally) losetup - A tool to set up and control loop devices + A tool to set up and control loop devices. * (optionally) pvdisplay/vgchange: - A tool to display/change physical volume attribute + A tool to display/change physical volume attribute. * (optionally) ssh-keygen - A tool to provide the authentication key generation, management and conversion + A tool to provide the authentication key generation, management and conversion. Test method --------------- @@ -54,15 +73,45 @@ Test method - Translate this address untill we get the physical address on the host OS -- Software injects an SRAO MCE at that physical address from host OS +- Software injects an SRAO error via mce-inject on that physical address from host OS -- (optionally) Write to the address from the guest, i.e attempt to +- Or inject an SRAR error via EINJ at that physical address from host OS + +- (optionally) Read/Write on the same address from the guest, i.e. attempt to write to the poisoned page from the guest. -the expected result: +- NOTE: SRAR error must be injected via EINJ rather than mce-inject. It is because + SRAR error can be generated only in the process context in which it is triggered, + so if injected via mce-inject, the error is triggered in mce-inject execution + context but not in QEMU's. Host kernel will not send signal SRAR to QEMU. + On the other hand, if injected via EINJ in host but triggered in VM/QEMU, + QEMU can receive signal SRAR correctly from host kernel. -HOST system dmesg: +The test command and expected result, i.e, lists as below: +---------------- + +1. for SRAO error: + +bash> ./host_run.sh -t spoof -i test.qcow2 -f SRAO + 2 logical volume(s) in volume group "VolGroup" now active +mount LVM image to /tmp/tmp.qFt9RbQhkk + 0 logical volume(s) in volume group "VolGroup" now active +/dev/nbd0 disconnected +Start the default kernel on guest system,test.qcow2 +monitor console is /dev/pts/0 +serial console is /dev/pts/1 +Waiting for guest system start up... +Guest physical address is 0x6e0a7000 +Host virtual address is 7fbfe9ea7 +Host physical address is 0x8092a7000 +calling mce-inject /root/mce-test/cases/function/kvm/host/mce_inject_data +Guest physical klog address is 0x6e0a7 +localhost.localdomain login: MCE 0x6e0a7: Killing simple_process:3230 due to hardware memory corruption +MCE 0x6e0a7: recovery action for dirty LRU page: Recovered +PASS: Inject error into guest! +PASS: Guest System alive! +HOST system dmesg: ... Machine check injector initialized Triggering MCE exception on CPU 0 @@ -73,7 +122,6 @@ MCE 0x806324: Killing qemu-system-x86:8829 early due to hardware memory corrupti MCE 0x806324: dirty LRU page recovery: Recovered ... - GUEST system dmesg: ... [Hardware Error]: Machine check events logged @@ -81,6 +129,64 @@ MCE 0x75925: Killing simple_process:2273 early due to hardware memory corruption MCE 0x75925: dirty LRU page recovery : Recovered ... +2. for SRAR error: + +bash> ./host_run.sh -t real -i test.qcow2 + 2 logical volume(s) in volume group "VolGroup" now active +mount LVM image to /tmp/tmp.2wbxFrY3Sd + 0 logical volume(s) in volume group "VolGroup" now active +/dev/nbd0 disconnected +Start the default kernel on guest system,test.qcow2 +monitor console is /dev/pts/0 +serial console is /dev/pts/1 +Waiting for guest system start up... +Guest physical address is 0x6e3a0000 +Host virtual address is 0x7fb1f21a0000 +Host physical address is 0x4225a0000 +calling apei_inj 0x4225a0000 +SRAR error triggered successfully +LMCE happens +PASS: Inject error into guest! +PASS: Guest System alive! + +Host mcelog information: + +Hardware event. This is not a software error. +MCE 0 +CPU 2 BANK 1 TSC 76f903d0667e +MISC 86 ADDR 4225a0000 +TIME 1446728506 Thu Nov 5 08:01:46 2015 +MCG status:RIPV EIPV MCIP +MCi status: +Uncorrected error +Error enabled +MCi_MISC register valid +MCi_ADDR register valid +SRAR +MCA: Data CACHE Level-0 Data-Read Error +STATUS bd80002000100134 MCGSTATUS 7 +MCGCAP 7000c16 APICID 4 SOCKETID 0 +CPUID Vendor Intel Family 6 Model 63 + +Guest mcelog information: + +Hardware event. This is not a software error. +MCE 0 +CPU 1 BANK 9 TSC 22b34556c4 +RIP 33:401311 +MISC 8c ADDR 6e3a0000 +TIME 1446728507 Thu Nov 5 08:01:47 2015 +MCG status:EIPV MCIP LMCE +MCi status: +Uncorrected error +Error enabled +MCi_MISC register valid +MCi_ADDR register valid +SRAR +MCA: Data CACHE Level-0 Data-Read Error +STATUS bd80000000000134 MCGSTATUS e +MCGCAP 900010a APICID 1 SOCKETID 1 +CPUID Vendor Intel Family 6 Model 60 Installation --------------- @@ -95,50 +201,49 @@ Installation CONFIG_ARCH_SUPPORTS_MEMORY_FAILURE=y CONFIG_MEMORY_FAILURE=y - NOTE: if the host machine doesn't support software error recovery + NOTE: if host machine doesn't support software error recovery (MCG_SER_P in IA32_MCG_CAP[24]), please apply the patch fake_ser_p.patch under ./patches/ 2. Use ssh-keygen to generate public and privite keys on the host OS, and copy id_rsa and id_rsa.pub from ~/.ssh/ into the testing directory on the host system. -3. compile and install qemu-kvm - the qemu-kvm source can be got from git://git.kernel.org/pub/scm/virt/kvm/qemu-kvm.git. - Before compile qemu-kvm, a patch p2v.patch should be applied. This patch - is located under ./patches/ +3. compile and install QEMU + The QEMU source can be got from git://git.qemu-project.org/qemu.git. + To build QEMU, under QEMU directory, run ./configure --target-list=x86_64-softmmu + --disable-strip, and then make;make install. Please ensure *SDL-devel* library is installed on the host machine, otherwise - only VNC can be used substituing local graphic output. -4. install the guest OS on the qemu - e.g. + only VNC can be used to substitue local graphic output. +4. install the guest OS on the QEMU + e.g. step 1: qemu-img create -f qcow2 test.img 10G step 2: qemu-system-x86_64 -hda ./test.img -m 2048 -cdrom rhel6.iso -boot d after the installation, please be sure to execute the following check: a) add necessary command line parameters under your boot item. - This is to enable console output redirection to the serial. - e.g. - before: - title Red Hat Enterprise Linux Server (2.6.32kvm) - root (hd0,1) - kernel /boot/vmlinuz-2.6.32kvm ro root=/dev/sda1 - initrd /boot/initramfs-2.6.32kvm.img - after: - title Red Hat Enterprise Linux Server (2.6.32kvm) - root (hd0,1) - kernel /boot/vmlinuz-2.6.32kvm ro root=/dev/sda1 console=tty0 console=ttyS0,115200n8 - initrd /boot/initramfs-2.6.32kvm.img + This is to enable console output redirection to the serial. + e.g. + before: + title Red Hat Enterprise Linux Server (2.6.32kvm) + root (hd0,1) + kernel /boot/vmlinuz-2.6.32kvm ro root=/dev/sda1 + initrd /boot/initramfs-2.6.32kvm.img + after: + title Red Hat Enterprise Linux Server (2.6.32kvm) + root (hd0,1) + kernel /boot/vmlinuz-2.6.32kvm ro root=/dev/sda1 console=tty0 console=ttyS0,115200n8 + initrd /boot/initramfs-2.6.32kvm.img b) DHCP guest ethernet card. This operation is to ensure the network connection - is OK. - e.g. - bash> dhclient eth0 + is OK. + e.g. + bash> dhclient eth0 c) enable SSH public/private key authorization, otherwise, the SSH connection password - is necessary to be provided in the test progress. - please check /etc/ssh/ssd_config and ensure related options are opened. - e.g. - RSAAuthentication yes - PubkeyAuthentication yes - after the related options are opened, please restart ssh service - e.g. - bash> service sshd restart - + is necessary to be provided in the test progress. + please check /etc/ssh/ssd_config and ensure related options are opened. + e.g. + RSAAuthentication yes + PubkeyAuthentication yes + after the related options are opened, please restart ssh service + e.g. + bash> service sshd restart Start Testing --------------- diff --git a/cases/function/kvm/guest/guest_run.sh b/cases/function/kvm/guest/guest_run_simple.sh index 0f5886b..fe72819 100755..100644 --- a/cases/function/kvm/guest/guest_run.sh +++ b/cases/function/kvm/guest/guest_run_simple.sh @@ -1,6 +1,6 @@ #!/bin/bash # -# Test script for KVM RAS +# Test script for SRAO error injection # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public @@ -21,12 +21,19 @@ # killall simple_process +cat /dev/null > /var/log/mcelog +sleep 1 -cd GUEST_DIR +cd GUEST_DIR/simple_process +gcc -o simple_process simple_process.c +cd ../page-types +gcc -o page-types page-types.c +cd .. -./simple_process > /dev/null & +./simple_process/simple_process > /dev/null & +sleep 1 -./page-types -p `pidof simple_process` -LN -b anon > guest_page +./page-types/page-types -p `pidof simple_process` -LN -b anon > guest_page if [ -s guest_page ]; then ADDR_KLOG=`awk 'NR > 3 {print "0x"$2}' guest_page | sed -n -e '1p'` ADDR=`echo $ADDR_KLOG"000"` diff --git a/cases/function/kvm/guest/guest_run_victim.sh b/cases/function/kvm/guest/guest_run_victim.sh new file mode 100644 index 0000000..4743aa3 --- /dev/null +++ b/cases/function/kvm/guest/guest_run_victim.sh @@ -0,0 +1,38 @@ +#!/bin/bash +# +# Test script for SRAR error injection +# +# 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) 2015, Intel Corp. +# Author: Wen Jin <wenx.jin@intel.com> +# + +killall victim +cat /dev/null > /var/log/mcelog +sleep 1 + +cd GUEST_DIR/victim +gcc -o victim victim.c +cd .. + +./victim/victim -k 0 -d > guest_phys & +sleep 1 + +if [ -s guest_phys ]; then + ADDR=`cat guest_phys | awk '{print $NF}'` + echo "guest physical address is $ADDR" > guest_tmp +fi + diff --git a/cases/function/kvm/host/host_run.sh b/cases/function/kvm/host/host_run.sh index 500e275..f17b25a 100755 --- a/cases/function/kvm/host/host_run.sh +++ b/cases/function/kvm/host/host_run.sh @@ -16,10 +16,73 @@ # 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. +# Copyright (C) 2010-2015, Intel Corp. # Author: Jiajia Zheng <jiajia.zheng@intel.com> +# Author: Wen Jin <wenx.jin@intel.com> # +export ROOT=`(cd ../../../../; pwd)` + +. $ROOT/lib/functions.sh +setup_path +. $ROOT/lib/mce.sh + +inject_type=0x00000010 +EDAC_TYPE="" +g_debugfs="" + +complain() +{ + echo $* + exit 1 +} + +apei_inj() +{ + echo $inject_type > $g_debugfs/apei/einj/error_type + echo $1 > $g_debugfs/apei/einj/param1 + echo 0xfffffffffffff000 > $g_debugfs/apei/einj/param2 + echo 1 > $g_debugfs/apei/einj/notrigger + echo 1 > $g_debugfs/apei/einj/error_inject +} + +check_einj() +{ + check_debugfs + + g_debugfs=`cat /proc/mounts | grep debugfs | cut -d ' ' -f2 | head -1` + #if einj is not builtin, just insmod it + if [ ! -d $g_debugfs/apei/einj ]; then + #if einj is a module, it is ensured to have been loaded + modprobe einj param_extension=1 > /dev/null 2>&1 + [ $? -eq 0 ] || complain "module einj isn't supported?" + fi + [ -f $g_debugfs/apei/einj/param1 ] || complain "No BIOS extension support for APEI on this platform" + [ -f $g_debugfs/apei/einj/notrigger ] || + complain "No parameter *notrigger*. Injection maybe causes system crash. Please check commit v3.3-3-gee49089" + + #check if the platform supports Uncorrectable non-fatal Memory Error injection + cat $g_debugfs/apei/einj/available_error_type | grep -q $inject_type + if [ $? -ne 0 ]; then + complain "Uncorrectable non-fatal Memory Error is not supported" + fi +} + +rm_edac() +{ + # 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 +} + image="" mce_inject_file="" @@ -31,25 +94,29 @@ RAM_size="" kernel="" initrd="" root="" +test_type="" +format="" +trigger_file="trigger_start" usage() { echo "Usage: ./host_run.sh [-options] [arguments]" echo "================Below are the must have options===============" + echo -e "\t-t test_type\t: spoof(mce_inject) or real(einj)" 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-f mcefile\t: which mce data file to inject" echo -e "\t-d hostdir\t: where you put the test scripts on host system" echo -e "\t\t\tBe careful to change it" echo -e "\t-g guestdir\t: where you put the test scripts on guest system" echo -e "\t\t\tBy default, guestdir is set to $GUEST_DIR" echo -e "\t-o offset\t: guest image offset" echo -e "\t\t\tBy default, offset is calculated by kpartx " - echo -e "\t-l\t\t: late kill, disable early kill in guest system" - echo -e "\t\t\tBy default, earlykill is enabled " - echo -e "\t-m ramsize\t: virtual RAM size of guest system" - echo -e "\t\t\tBy default, qemu-kvm defaults to 512M bytes" - echo -e "\t-h\t\t: show this help" + echo -e "\t-l\t\t: late kill, disable early kill in guest system" + echo -e "\t\t\tBy default, earlykill is enabled " + echo -e "\t-m ramsize\t: virtual RAM size of guest system" + echo -e "\t\t\tBy default, qemu-kvm defaults to 2048M bytes" + echo -e "\t-h\t\t: show this help" echo "============If you want to specify the guest kernel===========" echo "============please set below options all together=============" echo -e "\t-k kernel\t: guest kernel" @@ -58,9 +125,10 @@ usage() exit 0 } -while getopts "i:f:d:g:o:b:p:k:n:r:hlm:" option +while getopts "i:f:d:g:o:b:p:k:n:r:t:hlm:" option do - case $option in + case $option in + t) test_type=$OPTARG;; i) image=$OPTARG;; f) mce_inject_file=$OPTARG;; d) HOST_DIR=$OPTARG;; @@ -73,11 +141,13 @@ do m) RAM_size=$OPTARG;; h) usage;; *) echo 'invalid option!'; usage;; - esac + esac done - -guest_script=$GUEST_DIR/guest_run.sh +script_simple=guest_run_simple.sh +script_victim=guest_run_victim.sh +guest_script_simple=$GUEST_DIR/$script_simple +guest_script_victim=$GUEST_DIR/$script_victim guest_tmp=$GUEST_DIR/guest_tmp guest_page=$GUEST_DIR/guest_page GUEST_PHY="" @@ -93,7 +163,8 @@ host_tmp=$HOST_DIR/host_tmp mce_inject_data=$HOST_DIR/mce_inject_data monitor_console="" serial_console="" - +NBD_MAJOR="43" +NBD_DEV="/dev/nbd0" invalid() { @@ -109,37 +180,78 @@ check_env() exit 1 fi - if modinfo mce_inject &> /dev/null; then + if modinfo mce_inject >/dev/null 2>&1; then if ! lsmod | grep -q mce_inject; then if ! modprobe mce_inject; then - invalid "module mce_inject isn't supported ?" + complain "module mce_inject isn't supported ?" fi fi fi - which kpartx &>/dev/null - [ ! $? -eq 0 ] && invalid "please install kpartx tool!" - which mce-inject &>/dev/null - [ ! $? -eq 0 ] && invalid "please install mce-inject tool!" - - [ -z $RAM_size ] && RAM_size=512 - [ -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!" + which qemu-img >/dev/null 2>&1 + [ ! $? -eq 0 ] && complain "please install qemu-img tool!" + which kpartx >/dev/null 2>&1 + [ ! $? -eq 0 ] && complain "please install kpartx tool!" + which losetup >/dev/null 2>&1 + [ ! $? -eq 0 ] && complain "please install losetup tool!" + which pvdisplay >/dev/null 2>&1 + [ ! $? -eq 0 ] && complain "please install pvdisplay tool!" + which vgchange >/dev/null 2>&1 + [ ! $? -eq 0 ] && complain "please install vgchange tool!" + which mce-inject >/dev/null 2>&1 + [ ! $? -eq 0 ] && complain "please install mce-inject tool!" + + [ -z $RAM_size ] && RAM_size=2048 + if [ -z $test_type ] || [ "$test_type" != "spoof" ] && [ "$test_type" != "real" ] + then + invalid "please input inject type: spoof or real!" + fi + [ -z ${image} ] && invalid "please input the guest image!" + [ ! -e ${image} ] && invalid "guest image ${image} does not exist!" + if [ "$test_type" == "spoof" ]; then + [ -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!" + fi - [ ! -e $host_key_pub ] && invalid "host public key does not exist!" - [ ! -e $host_key_priv ] && invalid "host privite key does not exist!" + [ ! -e $host_key_pub ] && complain "host public key does not exist!" + [ ! -e $host_key_priv ] && complain "host privite key does not exist!" chmod 600 $host_key_pub chmod 600 $host_key_priv + if [ "$test_type" == "real" ]; then + [ -e $ROOT/bin/victim ] || complain "file victim does not exist!" \ + "maybe you forget to run make install under directory $ROOT before test" + check_einj + rm_edac + elif [ "$test_type" == "spoof" ]; then + [ -e $ROOT/bin/page-types ] || complain "file page-types does not exist!"\ + "maybe you forget to run make install under directory $ROOT before test" + fi } mount_image() { + local filename + mnt=`mktemp -d` - offset=`kpartx -l $image | awk '/loop deleted/ {next}; \ + filename=${image} + format=`qemu-img info ${image} | awk -F ': ' '/file format/ {print $NF}'` + if [ "$format" != "raw" ]; then + which qemu-nbd >/dev/null 2>&1 + [ ! $? -eq 0 ] && complain "please install qemu-nbd tool!" + if [ ! -b $NBD_DEV ] || [ `ls -l $NBD_DEV | awk '{print $5}' | cut -b 1-2` != $NBD_MAJOR ]; then + modprobe nbd >/dev/null 2>&1 + [ $? -eq 0 ] || complain "module nbd isn't supported?" + fi + qemu-nbd -d $NBD_DEV + sleep 1 + qemu-nbd -c $NBD_DEV ${image} + sleep 1 + filename=$NBD_DEV + fi + + offset=`kpartx -l ${filename} | awk '/loop deleted/ {next}; \ {offset=$NF*512}; END {print offset}'` - mount_err=`mount -oloop,offset=$offset $image $mnt 2>&1` + mount_err=`mount -oloop,offset=$offset ${filename} $mnt 2>&1` if [ $? -eq 0 ]; then fs_type=unset echo "mount image to $mnt" @@ -148,40 +260,61 @@ mount_image() #See if we're dealing with a LVM filesystem type fs_type=`echo $mount_err | awk '/^mount: unknown filesystem type/ {print $NF}'` - if [ $fs_type != "'LVM2_member'" ]; then + if [ "$fs_type" != "'LVM2_member'" ]; then echo unknown filesystem type rm -rf $mnt + if [ "$format" != "raw" ]; then + qemu-nbd -d $NBD_DEV + fi return 1 fi - which losetup &>/dev/null - [ ! $? -eq 0 ] && invalid "please install losetup tool!" - which pvdisplay &>/dev/null - [ ! $? -eq 0 ] && invalid "please install pvdisplay tool!" - which vgchange &>/dev/null - [ ! $? -eq 0 ] && invalid "please install vgchange tool!" - #Try mounting the LVM image - loop_dev=`losetup -o ${offset} -f --show ${image}` - if [ -z ${loop_dev} ]; then + loop_dev=`losetup -o ${offset} -f --show ${filename}` + sleep 1 + if [ -z "${loop_dev}" ]; then echo no available loop device rm -rf $mnt + if [ "$format" != "raw" ]; then + qemu-nbd -d $NBD_DEV + fi return 1 fi + vg=`pvdisplay ${loop_dev} | awk '/ VG Name/ {print $NF}'` - lv=lv_root + if [ -z "${vg}" ]; then + losetup -d ${loop_dev} + rm -rf $mnt + if [ "$format" != "raw" ]; then + qemu-nbd -d $NBD_DEV + fi + return 1 + fi + vgchange -a ey ${vg} - if [ ! -b /dev/mapper/${vg}-${lv} ]; then + sleep 1 + #The device name under the /dev/mapper directory consists of vg(volume group) name + #and lv(logical volume) name, in which the char '-' will be replaced with "--" + #in the vg name part if it exists. + devmap_vg=`echo ${vg} | sed 's/-/--/g'` + devmap_root=`find /dev/mapper -name "${devmap_vg}*root" -print` + if [ ! -b "${devmap_root}" ]; then echo '! block special' losetup -d ${loop_dev} rm -rf $mnt + if [ "$format" != "raw" ]; then + qemu-nbd -d $NBD_DEV + fi return 1 fi - mount /dev/mapper/${vg}-${lv} $mnt + mount ${devmap_root} $mnt if [ $? -ne 0 ]; then vgchange -a en ${vg} losetup -d ${loop_dev} rm -rf $mnt + if [ "$format" != "raw" ]; then + qemu-nbd -d $NBD_DEV + fi return 1 fi echo "mount LVM image to $mnt" @@ -192,11 +325,14 @@ umount_image() { umount $mnt sleep 2 - if [ $fs_type = "'LVM2_member'" ]; then + if [ "$fs_type" = "'LVM2_member'" ]; then vgchange -a en ${vg} losetup -d ${loop_dev} fi rm -rf $mnt + if [ "$format" != "raw" ]; then + qemu-nbd -d $NBD_DEV + fi } #Guest Image Preparation @@ -218,16 +354,26 @@ image_prepare() chmod 700 $mnt/root/.ssh fi mkdir -p $mnt/$GUEST_DIR - cp ../guest/guest_run.sh $mnt/$GUEST_DIR - gcc -o simple_process ../../tools/simple_process/simple_process.c - gcc -o page-types ../../tools/page-types.c - cp simple_process $mnt/$GUEST_DIR - cp page-types $mnt/$GUEST_DIR - sed -i -e "s#GUEST_DIR#$GUEST_DIR#g" $mnt/$guest_script + if [ "$test_type" == "real" ]; then + rm -f $mnt/$GUEST_DIR/$trigger_file + cp -f ../guest/$script_victim $mnt/$GUEST_DIR + cp -rf $ROOT/tools/victim $mnt/$GUEST_DIR + elif [ "$test_type" == "spoof" ]; then + cp -f ../guest/$script_simple $mnt/$GUEST_DIR + cp -rf $ROOT/tools/simple_process $mnt/$GUEST_DIR + cp -rf $ROOT/tools/page-types $mnt/$GUEST_DIR + fi cat $host_key_pub >> $mnt/root/.ssh/authorized_keys - kvm_ras=/etc/init.d/kvm_ras - sed -e "s#EARLYKILL#$early_kill#g" \ - -e "s#GUESTRUN#$guest_script#g" $guest_init > $mnt/$kvm_ras + kvm_ras=/etc/init.d/kvm_ras + if [ "$test_type" == "real" ]; then + sed -i -e "s#GUEST_DIR#$GUEST_DIR#g" $mnt/$guest_script_victim + sed -e "s#EARLYKILL#$early_kill#g" \ + -e "s#GUESTRUN#$guest_script_victim#g" $guest_init > $mnt/$kvm_ras + elif [ "$test_type" == "spoof" ]; then + sed -i -e "s#GUEST_DIR#$GUEST_DIR#g" $mnt/$guest_script_simple + sed -e "s#EARLYKILL#$early_kill#g" \ + -e "s#GUESTRUN#$guest_script_simple#g" $guest_init > $mnt/$kvm_ras + fi chmod a+x $mnt/$kvm_ras ln -s $kvm_ras $mnt/etc/rc${i}.d/S99kvm_ras sleep 2 @@ -242,7 +388,7 @@ start_guest() 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" \ + qemu-system-x86_64 -hda ${image} -kernel $kernel -initrd $initrd --append "$append" \ -m $RAM_size -net nic,model=rtl8139 -net user,hostfwd=tcp::5555-:22 \ -monitor pty -serial pty -pidfile $pid_file > $host_start 2>&1 & sleep 5 @@ -253,14 +399,14 @@ start_guest() invalid "please specify the guest initrd!" fi else - echo "Start the default kernel on guest system" - qemu-system-x86_64 -hda $image \ + echo "Start the default kernel on guest system,${image}" + qemu-system-x86_64 -smp 2 -machine accel=kvm -drive file=${image},format=$format \ -m $RAM_size -net nic,model=rtl8139 -net user,hostfwd=tcp::5555-:22 \ -monitor pty -serial pty -pidfile $pid_file > $host_start 2>&1 & - sleep 5 + sleep 10 fi - monitor_console=`awk '{print $NF}' $host_start | sed -n -e '1p'` - serial_console=`awk '{print $NF}' $host_start | sed -n -e '2p'` + monitor_console=`awk '{print $5}' $host_start | sed -n -e '1p'` + serial_console=`awk '{print $5}' $host_start | sed -n -e '2p'` QEMU_PID=`cat $pid_file` echo "monitor console is $monitor_console" echo "serial console is $serial_console" @@ -272,7 +418,7 @@ check_guest_alive() for i in 1 2 3 4 5 6 7 8 9 do sleep 10 - ssh -i $host_key_priv -o StrictHostKeyChecking=no localhost -p 5555 echo "" > /dev/null 2>&1 + ssh -i $host_key_priv -o StrictHostKeyChecking=no 127.0.0.1 -p 5555 echo "" > /dev/null 2>&1 if [ $? -eq 0 ]; then return 0 else @@ -285,8 +431,8 @@ check_guest_alive() addr_translate() { #Get Guest physical address - scp -o StrictHostKeyChecking=no -i $host_key_priv -P 5555 \ - localhost:$guest_tmp $HOST_DIR/guest_tmp > /dev/null 2>&1 + scp -o StrictHostKeyChecking=no -i $host_key_priv -P 5555 \ + 127.0.0.1:$guest_tmp $HOST_DIR/guest_tmp > /dev/null 2>&1 if [ $? -ne 0 ]; then echo "Failed to get Guest physical address, quit testing!" kill -9 $QEMU_PID @@ -301,29 +447,53 @@ addr_translate() echo x-gpa2hva $GUEST_PHY > $monitor_console cat $monitor_console > $monitor_console_output & sleep 5 - HOST_VIRT=`awk '/qemu|QEMU/{next} {print $NF}' $monitor_console_output |cut -b 3-11` + if [ "$test_type" == "real" ]; then + HOST_VIRT=`awk '/x-gpa2hva|qemu|QEMU/{next} {print $NF}' $monitor_console_output` + elif [ "$test_type" == "spoof" ]; then + HOST_VIRT=`awk '/x-gpa2hva|qemu|QEMU/{next} {print $NF}' $monitor_console_output |cut -b 3-11` + fi echo "Host virtual address is $HOST_VIRT" #Get Host physical address - ./page-types -p $QEMU_PID -LN -b anon | grep $HOST_VIRT > $host_tmp + if [ "$test_type" == "real" ]; then + victim -a vaddr=$HOST_VIRT,pid=$QEMU_PID > $host_tmp + elif [ "$test_type" == "spoof" ]; then + page-types -p $QEMU_PID -LN | grep $HOST_VIRT > $host_tmp + fi sleep 5 - ADDR=`cat $host_tmp | awk '{print "0x"$2"000"}' ` + if [ "$test_type" == "real" ]; then + ADDR=`cat $host_tmp | awk '{print $NF}'` + elif [ "$test_type" == "spoof" ]; then + ADDR=`cat $host_tmp | awk '{print "0x"$2"000"}' ` + fi echo "Host physical address is $ADDR" } error_inj() { - #Inject SRAO error - cat $mce_inject_file > $mce_inject_data - echo "ADDR $ADDR" >> $mce_inject_data - echo "calling mce-inject $mce_inject_data" - mce-inject $mce_inject_data + if [ "$test_type" == "real" ]; then + #Inject via APEI + echo "calling apei_inj $ADDR" + apei_inj $ADDR + sleep 1 + touch $HOST_DIR/$trigger_file + echo "trigger" > $HOST_DIR/$trigger_file + scp -o StrictHostKeyChecking=no -i $host_key_priv -P 5555 $HOST_DIR/$trigger_file \ + 127.0.0.1:$GUEST_DIR > /dev/null 2>&1 + elif [ "$test_type" == "spoof" ]; then + #Inject via mce_inject + cat $mce_inject_file > $mce_inject_data + echo "ADDR $ADDR" >> $mce_inject_data + echo "calling mce-inject $mce_inject_data" + mce-inject $mce_inject_data + fi + } get_guest_klog() { - cat $serial_console > $serial_console_output & + cat $serial_console > $serial_console_output & } check_guest_klog() @@ -338,6 +508,22 @@ check_guest_klog() } +check_srar_lmce_log() +{ + ssh -i $host_key_priv -o StrictHostKeyChecking=no 127.0.0.1 -p 5555 \ + "cat /var/log/mcelog" >> $serial_console_output + cat $serial_console_output | grep -q "SRAR" + if [ $? -ne 0 ]; then + return 1 + fi + echo "SRAR error triggered successfully" + cat $serial_console_output | grep -q "LMCE" + if [ $? -eq 0 ]; then + echo "LMCE happens" + fi + return 0 +} + check_env image_prepare @@ -348,29 +534,36 @@ else get_guest_klog check_guest_alive if [ $? -ne 0 ]; then - echo 'Start Guest system failed, quit testing!' + echo 'Start Guest system failed, quit testing!' else sleep 5 - addr_translate - error_inj + addr_translate + error_inj sleep 5 - check_guest_klog + if [ "$test_type" == "real" ]; then + check_srar_lmce_log + elif [ "$test_type" == "spoof" ]; then + check_guest_klog + fi if [ $? -ne 0 ]; then - echo 'FAIL: Did not get expected log!' - kill -9 $QEMU_PID + echo 'FAIL: Did not get expected log!' + kill -9 $QEMU_PID exit 1 else echo 'PASS: Inject error into guest!' fi - sleep 10 check_guest_alive if [ $? -ne 0 ]; then - echo 'FAIL: Guest System could have died!' + echo 'FAIL: Guest System could have died!' else echo 'PASS: Guest System alive!' fi fi fi -rm -f guest_tmp $host_start $monitor_console_output $serail_console_output $host_tmp $pid_file $mce_inject_data -rm -f ./simple_process ./page-types +rm -f guest_tmp $host_start $monitor_console_output $serial_console_output $host_tmp $pid_file +if [ "$test_type" == "real" ]; then + rm -f $HOST_DIR/$trigger_file +elif [ "$test_type" == "spoof" ]; then + rm -f $mce_inject_data +fi diff --git a/cases/function/kvm/patches/p2v.patch b/cases/function/kvm/patches/p2v.patch deleted file mode 100644 index 328212b..0000000 --- a/cases/function/kvm/patches/p2v.patch +++ /dev/null @@ -1,94 +0,0 @@ -From 0f28a71580205954313a8f1b592c97f49f330f32 Mon Sep 17 00:00:00 2001 -From: root <root@Romely.(none)> -Date: Tue, 15 Mar 2011 11:03:13 -0400 -Subject: [PATCH 2/2] x-gpa2hva, translate guest physical address to host virtual address - -Add command x-gpa2hva to translate guest physical address to host -virtual address. Because gpa to hva translation is not consistent, so -this command is only used for debugging. - -The x-gpa2hva command provides one step in a chain of translations from -guest virtual to guest physical to host virtual to host physical. Host -physical is then used to inject a machine check error. As a -consequence the HWPOISON code on the host and the MCE injection code -in qemu-kvm are exercised. - -v3: - -- Rename to x-gpa2hva -- Remove QMP support, because gpa2hva is not consistent - -v2: - -- Add QMP support - -Signed-off-by: Max Asbock <masbock@linux.vnet.ibm.com> -Signed-off-by: Jiajia Zheng <jiajia.zheng@intel.com> -Signed-off-by: Huang Ying <ying.huang@intel.com> ---- - hmp-commands.hx | 15 +++++++++++++++ - monitor.c | 22 ++++++++++++++++++++++ - 2 files changed, 37 insertions(+), 0 deletions(-) - -diff --git a/hmp-commands.hx b/hmp-commands.hx -index 247fdf0..c7aaf1c 100644 ---- a/hmp-commands.hx -+++ b/hmp-commands.hx -@@ -330,6 +330,21 @@ Start gdbserver session (default @var{port}=1234) - ETEXI - - { -+ .name = "x-gpa2hva", -+ .args_type = "fmt:/,addr:l", -+ .params = "/fmt addr", -+ .help = "translate guest physical 'addr' to host virtual address, only for debugging", -+ .user_print = do_gpa2hva_print, -+ .mhandler.cmd_new = do_gpa2hva, -+ }, -+ -+STEXI -+@item x-gpa2hva @var{addr} -+@findex x-gpa2hva -+Translate guest physical @var{addr} to host virtual address, only for debugging. -+ETEXI -+ -+ { - .name = "x", - .args_type = "fmt:/,addr:l", - .params = "/fmt addr", -diff --git a/monitor.c b/monitor.c -index fdbf9f3..f18aa2a 100644 ---- a/monitor.c -+++ b/monitor.c -@@ -2749,6 +2749,28 @@ static void do_inject_mce(Monitor *mon, const QDict *qdict) - } - #endif - -+static void do_gpa2hva_print(Monitor *mon, const QObject *data) -+{ -+ QInt *qint; -+ -+ qint = qobject_to_qint(data); -+ monitor_printf(mon, "0x%lx\n", (unsigned long)qint->value); -+} -+ -+static int do_gpa2hva(Monitor *mon, const QDict *qdict, QObject **ret_data) -+{ -+ target_phys_addr_t paddr; -+ target_phys_addr_t size = TARGET_PAGE_SIZE; -+ void *vaddr; -+ -+ paddr = qdict_get_int(qdict, "addr"); -+ vaddr = cpu_physical_memory_map(paddr, &size, 0); -+ cpu_physical_memory_unmap(vaddr, size, 0, 0); -+ *ret_data = qobject_from_jsonf("%ld", (unsigned long)vaddr); -+ -+ return 0; -+} -+ - static int do_getfd(Monitor *mon, const QDict *qdict, QObject **ret_data) - { - const char *fdname = qdict_get_str(qdict, "fdname"); --- -1.7.1 - diff --git a/tools/simple_process/simple_process.c b/tools/simple_process/simple_process.c index b6d3c4c..66f945f 100644 --- a/tools/simple_process/simple_process.c +++ b/tools/simple_process/simple_process.c @@ -5,14 +5,11 @@ int main(void) { - void *p = malloc(128); - printf("allocating 128 bytes of memory\n"); - while (1) - { - memset(p, 0, 128); - } - return 0; -} - - + void *p = malloc(0x100000); + printf("allocating 1M bytes of memory\n"); + while (1) { + memset(p, 0, 0x100000); + } + return 0; +} |