aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChen Gong <gong.chen@linux.intel.com>2012-08-08 02:49:23 +0800
committerChen Gong <gong.chen@linux.intel.com>2012-08-21 23:20:50 -0400
commit85774fa104d86af2a75332d2c2851e98e3840c4d (patch)
tree47cfbf54ae652a246ddf4369238f2d6b942ee5e8
parent770e3763f97a5dc4738c50190e6491cefd271a4c (diff)
downloadmce-test-85774fa104d86af2a75332d2c2851e98e3840c4d.tar.gz
Add SRAR DCU/IFU functional test case
This patch adds two SRAR functinal test cases (DCU & IFU). The SRAR test is highly BIOS dependent so if BIOS is bogus, system will be hang or panic. By default these two test cases are disabled, if one wants to test SRAR, please open them. Signed-off-by: Chen Gong <gong.chen@linux.intel.com>
-rw-r--r--cases/function/Makefile3
-rw-r--r--cases/function/core_recovery/Makefile8
-rw-r--r--cases/function/core_recovery/core_recovery.c182
-rwxr-xr-xcases/function/core_recovery/runtest_dcu.sh33
-rwxr-xr-xcases/function/core_recovery/runtest_ifu.sh33
-rwxr-xr-xcases/function/core_recovery/srar_recovery.sh69
-rw-r--r--groups/function3
7 files changed, 331 insertions, 0 deletions
diff --git a/cases/function/Makefile b/cases/function/Makefile
index 6d66c0c..a94da1a 100644
--- a/cases/function/Makefile
+++ b/cases/function/Makefile
@@ -2,17 +2,20 @@ all:
$(MAKE) -C erst-inject
$(MAKE) -C pfa
$(MAKE) -C hwpoison
+ $(MAKE) -C core_recovery
# $(MAKE) -C kvm
clean:
$(MAKE) -C erst-inject clean
$(MAKE) -C pfa clean
$(MAKE) -C hwpoison clean
+ $(MAKE) -C core_recovery clean
# $(MAKE) -C kvm clean
install:
$(MAKE) -C erst-inject install
$(MAKE) -C pfa install
$(MAKE) -C hwpoison install
+ $(MAKE) -C core_recovery install
# $(MAKE) -C kvm install
diff --git a/cases/function/core_recovery/Makefile b/cases/function/core_recovery/Makefile
new file mode 100644
index 0000000..1b59dd1
--- /dev/null
+++ b/cases/function/core_recovery/Makefile
@@ -0,0 +1,8 @@
+CFLAGS := -Wall
+
+core_recovery: core_recovery.o
+
+install: core_recovery
+
+clean:
+ rm -f core_recovery *.o
diff --git a/cases/function/core_recovery/core_recovery.c b/cases/function/core_recovery/core_recovery.c
new file mode 100644
index 0000000..835c243
--- /dev/null
+++ b/cases/function/core_recovery/core_recovery.c
@@ -0,0 +1,182 @@
+/*
+ * Set up to get zapped by a machine check (injected elsewhere)
+ * To use this test case please ensure your SUT(System Under Test)
+ * can support MCE/SRAR.
+ *
+ * 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) 2012 Intel corporation
+ *
+ * Author:
+ * Tony Luck <tony.luck@intel.com>
+ * Gong Chen <gong.chen@intel.com>
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <time.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <sys/mman.h>
+
+/*
+ * Definition of /proc/pid/pagemap
+ * Bits 0-54 page frame number (PFN) if present
+ * Bits 0-4 swap type if swapped
+ * Bits 5-54 swap offset if swapped
+ * Bits 55-60 page shift (page size = 1<<page shift)
+ * Bit 61 reserved for future use
+ * Bit 62 page swapped
+ * Bit 63 page present
+ */
+
+struct pagemaps {
+ unsigned long long pfn:55;
+ unsigned long long pgshift:6;
+ unsigned long long rsvd:1;
+ unsigned long long swapped:1;
+ unsigned long long present:1;
+};
+
+static int pagesize;
+
+/*
+ * dummyfunc size should be less than one page after complied,
+ * otherwise, caller will not return from this function
+ */
+void dummyfunc(void)
+{
+ int fatarray[64];
+
+ fatarray[0] = 0xdeadbeaf;
+ fatarray[8] = 0xdeadbeaf;
+ fatarray[16] = 0xdeadbeaf;
+ fatarray[32] = 0xdeadbeaf;
+}
+
+/*
+ * get information about address from /proc/{pid}/pagemap
+ */
+unsigned long long vtop(unsigned long long addr)
+{
+ struct pagemaps pinfo;
+ unsigned int pinfo_size = sizeof pinfo;
+ long offset = addr / pagesize * pinfo_size;
+ int fd, pgmask;
+ char pagemapname[64];
+
+ sprintf(pagemapname, "/proc/%d/pagemap", getpid());
+ fd = open(pagemapname, O_RDONLY);
+ if (fd == -1) {
+ perror(pagemapname);
+ return 0;
+ }
+ if (pread(fd, (void*)&pinfo, pinfo_size, offset) != pinfo_size) {
+ perror(pagemapname);
+ close(fd);
+ return 0;
+ }
+ close(fd);
+ pgmask = (1 << pinfo.pgshift) - 1;
+ return (pinfo.pfn << pinfo.pgshift) | (addr & pgmask);
+}
+
+static void usage(void)
+{
+ printf(
+"core_recovery [options]\n"
+" -d|--data Inject data error(DCU error) under user context\n"
+" -i|--instruction Inject instruction error(IFU error) under user context\n"
+" -h|--help Show this usage message\n"
+ );
+}
+
+static const struct option opts[] = {
+ { "data" , 0, NULL, 'd' },
+ { "instruction" , 0, NULL, 'i' },
+ { "help" , 0, NULL, 'h' },
+ { NULL , 0, NULL, 0 }
+};
+
+int main(int argc, char **argv)
+{
+ unsigned long long phys;
+ long total;
+ char *buf, answer[16];
+ int c, i;
+ int iflag = 0, dflag = 0;
+ time_t now;
+
+ if (argc <= 1) {
+ usage();
+ return 0;
+ }
+
+ pagesize = getpagesize();
+
+ while ((c = getopt_long(argc, argv, "dih", opts, NULL)) != -1) {
+ switch (c) {
+ case 'd':
+ dflag = 1;
+ break;
+ case 'i':
+ iflag = 1;
+ break;
+ case 'h':
+ default:
+ usage();
+ return 0;
+ }
+ }
+
+ buf = mmap(NULL, pagesize, PROT_READ|PROT_WRITE|PROT_EXEC,
+ MAP_ANONYMOUS|MAP_PRIVATE|MAP_LOCKED, -1, 0);
+
+ if (buf == MAP_FAILED) {
+ fprintf(stderr, "Can't get a single page of memory!\n");
+ return 1;
+ }
+ memset(buf, '*', pagesize);
+ phys = vtop((unsigned long long)buf);
+ if (phys == 0) {
+ fprintf(stderr, "Can't get physical address of the page!\n");
+ return 1;
+ }
+
+ if (iflag)
+ memcpy(buf, (void*)dummyfunc, pagesize);
+
+ printf("physical address of (0x%llx) = 0x%llx\n"
+ "Hit any key to trigger error: ", (unsigned long long)buf, phys);
+ fflush(stdout);
+ read(0, answer, 16);
+ now = time(NULL);
+ printf("Access time at %s\n", ctime(&now));
+
+ if (iflag) {
+ void (*f)(void) = (void (*)(void))buf;
+
+ while (1) f() ;
+ }
+
+ if (dflag) {
+ while (1) {
+ for (i = 0; i < pagesize; i += sizeof(int))
+ total += *(int*)(buf + i);
+ }
+ }
+
+ return 0;
+}
diff --git a/cases/function/core_recovery/runtest_dcu.sh b/cases/function/core_recovery/runtest_dcu.sh
new file mode 100755
index 0000000..00040e7
--- /dev/null
+++ b/cases/function/core_recovery/runtest_dcu.sh
@@ -0,0 +1,33 @@
+#!/bin/sh
+# This test is the SRAR/DCU functional test.
+#
+
+cat <<-EOF
+
+***************************************************************************
+Pay attention:
+
+This test is SRAR functional test. It is for DCU part(L1 Data Cache). The
+test highly depends on BIOS implementation, which means if BIOS is bogus,
+it is possible to cause system hang/crash. If meeting this situation,
+please test again after rebooot or just skip this test.
+***************************************************************************
+
+
+EOF
+
+echo 0 > $TMP_DIR/error.$$
+
+pushd `dirname $0` > /dev/null
+./srar_recovery.sh -d
+[ $? -eq 0 ] || echo 1 > $TMP_DIR/error.$$
+popd > /dev/null
+
+grep -q "1" $TMP_DIR/error.$$
+if [ $? -eq 0 ]
+then
+ exit 1
+else
+ exit 0
+fi
+
diff --git a/cases/function/core_recovery/runtest_ifu.sh b/cases/function/core_recovery/runtest_ifu.sh
new file mode 100755
index 0000000..bb49a5b
--- /dev/null
+++ b/cases/function/core_recovery/runtest_ifu.sh
@@ -0,0 +1,33 @@
+#!/bin/sh
+# This test is the SRAR/DCU functional test.
+#
+
+cat <<-EOF
+
+***************************************************************************
+Pay attention:
+
+This test is SRAR functional test. It is for IFU part(L1 Instruction Cache).
+The test highly depends on BIOS implementation, which means if BIOS is bogus,
+it is possible to cause system hang/crash. If meeting this situation,
+please test again after rebooot or just skip this test.
+***************************************************************************
+
+
+EOF
+
+echo 0 > $TMP_DIR/error.$$
+
+pushd `dirname $0` > /dev/null
+./srar_recovery.sh -i
+[ $? -eq 0 ] || echo 1 > $TMP_DIR/error.$$
+popd > /dev/null
+
+grep -q "1" $TMP_DIR/error.$$
+if [ $? -eq 0 ]
+then
+ exit 1
+else
+ exit 0
+fi
+
diff --git a/cases/function/core_recovery/srar_recovery.sh b/cases/function/core_recovery/srar_recovery.sh
new file mode 100755
index 0000000..2b30a99
--- /dev/null
+++ b/cases/function/core_recovery/srar_recovery.sh
@@ -0,0 +1,69 @@
+#!/bin/sh
+
+#set -x
+export ROOT=`(cd ../../../; pwd)`
+
+. $ROOT/lib/mce.sh
+
+inject_type=0x00000010
+
+invalid()
+{
+ 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
+}
+
+print_usage()
+{
+ echo -e "usage:
+\t./srar_recovery.sh -d\t\tDCU error injection under user context
+\t./srar_recovery.sh -i\t\tIFU error injection under user context"
+}
+
+if [ "$1" != "-d" -a "$1" != "-i" ]; then
+ print_usage
+ exit 1
+fi
+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 ] || invalid "module einj isn't supported?"
+fi
+[ -f $g_debugfs/apei/einj/param1 ] || invalid "no BIOS extension support for APEI on this platform"
+
+#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
+ invalid "Uncorrectable non-fatal Memory Error is not supported"
+fi
+
+touch trigger
+tail -f trigger | ./core_recovery $1 > log &
+addr=`cat log |cut -d' ' -f6|head -1`
+apei_inj $addr
+sleep 1
+echo go > trigger
+sleep 2
+rm -f trigger log
+pgrep core_recovery > /dev/null 2>&1 | xargs kill -9 > /dev/null 2>&1
+[ $? -eq 0 ] && invalid "The poisoned process can't be killed by kernel. Test fails!"
+
+if [ $1 == "-d" ]; then
+ echo "SRAR/DCU test passes!"
+elif [ $1 == "-i" ]; then
+ echo "SRAR/IFU test passes!"
+fi
+
diff --git a/groups/function b/groups/function
index 1361121..f6c0d70 100644
--- a/groups/function
+++ b/groups/function
@@ -2,6 +2,9 @@ APEI-INJ cases/function/apei-inj/runtest.sh on
ERST-INJ cases/function/erst-inject/runtest.sh on
#PFA test depends on correct BIOS/mcelog setting
PFA cases/function/pfa/runtest.sh on
+#SRAR test highly depends on BIOS implementation
+SRAR-DCU cases/function/core_recovery/runtest_dcu.sh off
+SRAR-IFU cases/function/core_recovery/runtest_ifu.sh off
#HWpoison
HWPOISON-SOFT cases/function/hwpoison/run_soft.sh on
HWPOISON-HARD cases/function/hwpoison/run_hard.sh on