Update mce-test to HEAD.

Patches provided by Shaohui Zheng <shaohui.zheng@intel.com>.

Signed-off-by: Garrett Cooper <yanegomi@gmail.com>
diff --git a/README b/README
index 7f2dc6f..b426184 100644
--- a/README
+++ b/README
@@ -1,3 +1,36 @@
+MCE APEI INJ testing cases 
+=========================
+
+Nov 6th, 2009
+
+Jiajia Zheng
+
+Start
+------------
+This test suite is based on apei-inj APEI haredware injection tool. 
+It's structure and usage are the same with soft-inj test suite.
+To be root and invoke simple test driver on test configuration file as follow
+	drivers/simple/driver.sh config/simple_apei_ucr.conf
+
+Test Dependencies
+-----------------
+MCE APEI INJ test suite has following dependencies on kernel and other tools:
+
+* Make sure following configuration options are enabled in linux kernel:
+	CONFIG_FTRACE=y
+	CONFIG_FUNCTION_TRACER=y
+
+* 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).
+  For detail, please see 3.4 in doc/howto.txt.
+
+* simple-process:
+  APEI hardware injection will inject an error to a page used by this simple-process.  Intall simple-process.
+	cd mce-test/tools/simple_process
+	make
+
+
 Linux Test Project
 (Maintained by: Subrata Modak <subrata@linux.vnet.ibm.com>)
 
diff --git a/testcases/mce-test/Makefile b/testcases/mce-test/Makefile
index 5972106..f0cdc21 100644
--- a/testcases/mce-test/Makefile
+++ b/testcases/mce-test/Makefile
@@ -1,27 +1,41 @@
+.PHONY:	test clean distclean reset test-simple test-kdump
 
 all:
 	$(MAKE) -C tools
 	$(MAKE) -C tsrc
+	$(MAKE) -C stress
 
 clean:
 	$(MAKE) -C tools clean
 	$(MAKE) -C tsrc clean
+	$(MAKE) -C stress clean
 	$(MAKE) reset
 
 distclean:
 	$(MAKE) -C tools distclean
 	$(MAKE) -C tsrc distclean
+	$(MAKE) -C stress distclean
 	$(MAKE) reset
+	rm -rf bin/*
 
 reset:
 	rm -rf work/*
 	rm -rf results/*
 
-test:
-	$(MAKE) reset
-	./drivers/simple/driver.sh simple.conf
-	./drivers/kdump/driver.sh kdump.conf
+test: test-simple test-stress
 
 test-simple:
 	$(MAKE) reset
 	./drivers/simple/driver.sh simple.conf
+	$(MAKE) -C tsrc test
+
+# requires LTP & page-types to be installed
+test-stress:
+	$(MAKE) -C stress test
+
+# requires special packages to be installed
+test-kdump:
+	$(MAKE) reset
+	./drivers/simple/driver.sh simple.conf
+	./drivers/kdump/driver.sh kdump.conf
+	$(MAKE) -C tsrc test
diff --git a/testcases/mce-test/README b/testcases/mce-test/README
index 193ff15..6992755 100644
--- a/testcases/mce-test/README
+++ b/testcases/mce-test/README
@@ -33,9 +33,11 @@
 	Contains all test cases, which may be organized in
 	sub-directories, the interface of a class of test cases is a
 	shell script under cases/, such as:
-	    cases/soft-inj/panic/cases.sh
-	is for test cases triggered by soft-inject and my cause system
-	panic during testing.
+	   -- cases/soft-inj/panic/cases.sh
+		is for test cases triggered by soft-inject and may cause system 
+		panic during testing.
+	   -- cases/apei-inj/ucr/cases.sh  
+		is for test cases triggered by apei-inject.
 
 config/*
 	Contains test configuration files, which specifies the
@@ -80,12 +82,19 @@
 	Some tools used by test drivers or test cases will be
 	installed into this directory.
 
+stress/
+	Linux MCE stress test suite.
 
 Test Instruction
 ----------------
 
 Please refer to corresponding section in doc/howto.txt.
 
+Very quick way to test this:
+	be root
+	make sure you have a kernel with CONFIG_X86_MCE_INJECT
+	and CONFIG_HWPOISON_INJECT and soft-offlining support
+	run "make test"
 
 Futher Information
 ------------------
@@ -95,6 +104,8 @@
 
 doc/howto.txt:		a more detailed HOWTO document
 
+doc/stress-howto.txt:	Detailed HOWTO document for MCE stress test suite
+
 doc/cases/*.txt:	Description of every test case, including test
 			objective, code patch tested, reference and
 			expected results
diff --git a/testcases/mce-test/cases/soft-inj/non-panic/cases.sh b/testcases/mce-test/cases/soft-inj/non-panic/cases.sh
index 2c25906..d277e11 100755
--- a/testcases/mce-test/cases/soft-inj/non-panic/cases.sh
+++ b/testcases/mce-test/cases/soft-inj/non-panic/cases.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/bin/bash
 #
 # Software injection based test cases - non-panic cases: test cases
 # are triggered via the mce-inject tool, and they will not trigger kernel
diff --git a/testcases/mce-test/cases/soft-inj/panic/cases.sh b/testcases/mce-test/cases/soft-inj/panic/cases.sh
index 865e4ce..919f833 100755
--- a/testcases/mce-test/cases/soft-inj/panic/cases.sh
+++ b/testcases/mce-test/cases/soft-inj/panic/cases.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/bin/bash
 #
 # Software injection based test cases - panic cases: test cases are
 # triggered via the mce-inject tool, and they will trigger kernel panic.
diff --git a/testcases/mce-test/cases/soft-inj/panic/data/fatal b/testcases/mce-test/cases/soft-inj/panic/data/fatal
index a749a27..b24942b 100644
--- a/testcases/mce-test/cases/soft-inj/panic/data/fatal
+++ b/testcases/mce-test/cases/soft-inj/panic/data/fatal
@@ -3,6 +3,6 @@
 # don't try casually
 CPU 0 BANK 4
 MCGSTATUS MCIP
-STATUS FATAL
+STATUS FATAL S
 RIP 12343434
 MISC 11
diff --git a/testcases/mce-test/cases/soft-inj/panic/data/fatal_eipv b/testcases/mce-test/cases/soft-inj/panic/data/fatal_eipv
index 0208626..7e6a93a 100644
--- a/testcases/mce-test/cases/soft-inj/panic/data/fatal_eipv
+++ b/testcases/mce-test/cases/soft-inj/panic/data/fatal_eipv
@@ -3,5 +3,5 @@
 # don't try casually
 CPU 1 BANK 4
 MCGSTATUS MCIP EIPV
-STATUS FATAL
+STATUS FATAL S
 RIP 0x10:0x12343434
diff --git a/testcases/mce-test/cases/soft-inj/panic/data/fatal_irq b/testcases/mce-test/cases/soft-inj/panic/data/fatal_irq
index 2b1684d..63ef36b 100644
--- a/testcases/mce-test/cases/soft-inj/panic/data/fatal_irq
+++ b/testcases/mce-test/cases/soft-inj/panic/data/fatal_irq
@@ -3,7 +3,7 @@
 # don't try casually
 CPU 0 BANK 4
 MCGSTATUS MCIP
-STATUS FATAL
+STATUS FATAL S
 RIP 12343434
 MISC 11
 IN_IRQ
diff --git a/testcases/mce-test/cases/soft-inj/panic/data/fatal_no_en b/testcases/mce-test/cases/soft-inj/panic/data/fatal_no_en
index 03a24d1..12da496 100644
--- a/testcases/mce-test/cases/soft-inj/panic/data/fatal_no_en
+++ b/testcases/mce-test/cases/soft-inj/panic/data/fatal_no_en
@@ -3,6 +3,6 @@
 # don't try casually
 CPU 0 BANK 4
 MCGSTATUS MCIP
-STATUS UC VAL PCC
+STATUS UC VAL PCC S
 RIP 0x10:12343434
 MISC 11
diff --git a/testcases/mce-test/cases/soft-inj/panic/data/fatal_over b/testcases/mce-test/cases/soft-inj/panic/data/fatal_over
index 783c156..6f44419 100644
--- a/testcases/mce-test/cases/soft-inj/panic/data/fatal_over
+++ b/testcases/mce-test/cases/soft-inj/panic/data/fatal_over
@@ -3,7 +3,7 @@
 # don't try casually
 CPU 0 BANK 4
 MCGSTATUS MCIP
-STATUS FATAL OVER
+STATUS FATAL OVER S
 RIP 12343434
 MISC 11
 
diff --git a/testcases/mce-test/cases/soft-inj/panic/data/fatal_ripv b/testcases/mce-test/cases/soft-inj/panic/data/fatal_ripv
index e0af684..1978747 100644
--- a/testcases/mce-test/cases/soft-inj/panic/data/fatal_ripv
+++ b/testcases/mce-test/cases/soft-inj/panic/data/fatal_ripv
@@ -3,5 +3,5 @@
 # don't try casually
 CPU 1 BANK 4
 MCGSTATUS MCIP RIPV
-STATUS FATAL
+STATUS FATAL S
 RIP 0x10:0x12343434
diff --git a/testcases/mce-test/cases/soft-inj/panic/data/fatal_timeout b/testcases/mce-test/cases/soft-inj/panic/data/fatal_timeout
index 3083bd6..c910141 100644
--- a/testcases/mce-test/cases/soft-inj/panic/data/fatal_timeout
+++ b/testcases/mce-test/cases/soft-inj/panic/data/fatal_timeout
@@ -3,7 +3,7 @@
 # don't try casually
 CPU 0 BANK 4
 MCGSTATUS MCIP
-STATUS FATAL
+STATUS FATAL S
 RIP 0x10:0x12343434
 MISC 0xb
 NOBROADCAST
diff --git a/testcases/mce-test/cases/soft-inj/panic/data/fatal_timeout_ripv b/testcases/mce-test/cases/soft-inj/panic/data/fatal_timeout_ripv
index 623d563..0e34e00 100644
--- a/testcases/mce-test/cases/soft-inj/panic/data/fatal_timeout_ripv
+++ b/testcases/mce-test/cases/soft-inj/panic/data/fatal_timeout_ripv
@@ -3,7 +3,7 @@
 # don't try casually
 CPU 0 BANK 4
 MCGSTATUS MCIP RIPV
-STATUS FATAL
+STATUS FATAL S
 RIP 0x10:0x12343434
 MISC 0xb
 NOBROADCAST
diff --git a/testcases/mce-test/cases/soft-inj/panic/data/fatal_userspace b/testcases/mce-test/cases/soft-inj/panic/data/fatal_userspace
index 56c1f2e..3b8fe7f 100644
--- a/testcases/mce-test/cases/soft-inj/panic/data/fatal_userspace
+++ b/testcases/mce-test/cases/soft-inj/panic/data/fatal_userspace
@@ -3,5 +3,5 @@
 # don't try casually
 CPU 1 BANK 4
 MCGSTATUS MCIP EIPV
-STATUS FATAL
+STATUS FATAL S
 RIP 0x73:0x12343434
diff --git a/testcases/mce-test/cases/soft-inj/panic_noser/cases.sh b/testcases/mce-test/cases/soft-inj/panic_noser/cases.sh
index 7b6d127..9637b9b 100755
--- a/testcases/mce-test/cases/soft-inj/panic_noser/cases.sh
+++ b/testcases/mce-test/cases/soft-inj/panic_noser/cases.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/bin/bash
 #
 # Software injection based test cases: test cases are triggered via
 # the mce-inject tool.
diff --git a/testcases/mce-test/cases/soft-inj/panic_npcc/cases.sh b/testcases/mce-test/cases/soft-inj/panic_npcc/cases.sh
index d6d1e5a..35cc343 100755
--- a/testcases/mce-test/cases/soft-inj/panic_npcc/cases.sh
+++ b/testcases/mce-test/cases/soft-inj/panic_npcc/cases.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/bin/bash
 #
 # Software injection based test cases: test cases are triggered via
 # the mce-inject tool.
diff --git a/testcases/mce-test/cases/soft-inj/panic_npcc/data/fatal_severity b/testcases/mce-test/cases/soft-inj/panic_npcc/data/fatal_severity
index f46f222..4dfd8ed 100644
--- a/testcases/mce-test/cases/soft-inj/panic_npcc/data/fatal_severity
+++ b/testcases/mce-test/cases/soft-inj/panic_npcc/data/fatal_severity
@@ -12,5 +12,5 @@
 
 CPU 1 BANK 1
 MCGSTATUS MCIP
-STATUS FATAL
+STATUS FATAL S
 RIP 0x10:0xabcdcdcd
diff --git a/testcases/mce-test/cases/soft-inj/panic_npcc/data/uc_no_eripv b/testcases/mce-test/cases/soft-inj/panic_npcc/data/uc_no_eripv
index a317a1d..91f3b17 100644
--- a/testcases/mce-test/cases/soft-inj/panic_npcc/data/uc_no_eripv
+++ b/testcases/mce-test/cases/soft-inj/panic_npcc/data/uc_no_eripv
@@ -1,5 +1,5 @@
 CPU 0 BANK 1
-STATUS UNCORRECTED
+STATUS UNCORRECTED S
 MCGSTATUS MCIP
 ADDR 0x1234
 RIP 0x10:0xdeadbabe
diff --git a/testcases/mce-test/cases/soft-inj/panic_npcc/data/uc_no_eripv_timeout b/testcases/mce-test/cases/soft-inj/panic_npcc/data/uc_no_eripv_timeout
index 9fa29de..23cd098 100644
--- a/testcases/mce-test/cases/soft-inj/panic_npcc/data/uc_no_eripv_timeout
+++ b/testcases/mce-test/cases/soft-inj/panic_npcc/data/uc_no_eripv_timeout
@@ -1,5 +1,5 @@
 CPU 0 BANK 1
-STATUS UNCORRECTED
+STATUS UNCORRECTED S
 MCGSTATUS MCIP
 ADDR 0x1234
 RIP 0x10:0xdeadbabe
diff --git a/testcases/mce-test/cases/soft-inj/panic_npcc/data/uc_no_mcip b/testcases/mce-test/cases/soft-inj/panic_npcc/data/uc_no_mcip
index 51eeba4..c4ac81a 100644
--- a/testcases/mce-test/cases/soft-inj/panic_npcc/data/uc_no_mcip
+++ b/testcases/mce-test/cases/soft-inj/panic_npcc/data/uc_no_mcip
@@ -1,4 +1,4 @@
 CPU 0 BANK 1
-STATUS UNCORRECTED
+STATUS UNCORRECTED S
 ADDR 0x1234
 RIP 0x10:0xdeadbabe
diff --git a/testcases/mce-test/cases/soft-inj/panic_npcc/data/uc_no_mcip_timeout b/testcases/mce-test/cases/soft-inj/panic_npcc/data/uc_no_mcip_timeout
index 0126722..3f31a4f 100644
--- a/testcases/mce-test/cases/soft-inj/panic_npcc/data/uc_no_mcip_timeout
+++ b/testcases/mce-test/cases/soft-inj/panic_npcc/data/uc_no_mcip_timeout
@@ -1,5 +1,5 @@
 CPU 0 BANK 1
-STATUS UNCORRECTED
+STATUS UNCORRECTED S
 ADDR 0x1234
 RIP 0x10:0xdeadbabe
 NOBROADCAST
diff --git a/testcases/mce-test/cases/soft-inj/panic_npcc/data/uncorrected b/testcases/mce-test/cases/soft-inj/panic_npcc/data/uncorrected
index c270b29..7930350 100644
--- a/testcases/mce-test/cases/soft-inj/panic_npcc/data/uncorrected
+++ b/testcases/mce-test/cases/soft-inj/panic_npcc/data/uncorrected
@@ -1,7 +1,7 @@
 # this should just kill the process
 CPU 0 BANK 2
-STATUS UNCORRECTED
+STATUS UNCORRECTED S
 MCGSTATUS EIPV MCIP
 ADDR 0x1234
 RIP 0x10:0xdeadbabe
-IN_PROC
\ No newline at end of file
+IN_PROC
diff --git a/testcases/mce-test/cases/soft-inj/panic_npcc/data/uncorrected_timeout b/testcases/mce-test/cases/soft-inj/panic_npcc/data/uncorrected_timeout
index 6e627a7..4a469cd 100644
--- a/testcases/mce-test/cases/soft-inj/panic_npcc/data/uncorrected_timeout
+++ b/testcases/mce-test/cases/soft-inj/panic_npcc/data/uncorrected_timeout
@@ -1,6 +1,6 @@
 # this should just kill the process
 CPU 0 BANK 2
-STATUS UNCORRECTED
+STATUS UNCORRECTED S
 MCGSTATUS EIPV MCIP
 ADDR 0x1234
 RIP 0x10:0xdeadbabe
diff --git a/testcases/mce-test/cases/soft-inj/panic_npcc/data/unknown b/testcases/mce-test/cases/soft-inj/panic_npcc/data/unknown
index 007a980..25ecb5b1 100644
--- a/testcases/mce-test/cases/soft-inj/panic_npcc/data/unknown
+++ b/testcases/mce-test/cases/soft-inj/panic_npcc/data/unknown
@@ -1,3 +1,3 @@
 # this should just kill the process
 CPU 0 BANK 2
-STATUS UC
+STATUS UC S
diff --git a/testcases/mce-test/cases/soft-inj/panic_ucr/cases.sh b/testcases/mce-test/cases/soft-inj/panic_ucr/cases.sh
index b40fbfd..8aec7df 100755
--- a/testcases/mce-test/cases/soft-inj/panic_ucr/cases.sh
+++ b/testcases/mce-test/cases/soft-inj/panic_ucr/cases.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/bin/bash
 #
 # Software injection based test cases: test cases are triggered via
 # mce-inject tool.
diff --git a/testcases/mce-test/cases/soft-inj/poll_ucr/cases.sh b/testcases/mce-test/cases/soft-inj/poll_ucr/cases.sh
index 23f8c5e..dc9fc6a 100755
--- a/testcases/mce-test/cases/soft-inj/poll_ucr/cases.sh
+++ b/testcases/mce-test/cases/soft-inj/poll_ucr/cases.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/bin/bash
 #
 # Software injection based test cases: test cases are triggered via
 # mce-inject tool.
@@ -37,10 +37,15 @@
 {
     local removes="TSC TIME PROCESSOR"
     case "$bcase" in
-	ucna|ucna_over)
+	ucna|ucna_over|srar_poll)
 	    soft_inject_verify_mcelog
 	    verify_klog $klog
 	    ;;
+        fatal_poll)
+            removes="$removes RIP"
+            soft_inject_verify_mcelog
+            verify_klog $klog
+            ;;
 	*)
 	    echo "!!! Unknown case: $this_case !!!"
     esac
diff --git a/testcases/mce-test/cases/soft-inj/recoverable_ucr/cases.sh b/testcases/mce-test/cases/soft-inj/recoverable_ucr/cases.sh
index 61f1036..054a97b 100755
--- a/testcases/mce-test/cases/soft-inj/recoverable_ucr/cases.sh
+++ b/testcases/mce-test/cases/soft-inj/recoverable_ucr/cases.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/bin/bash
 #
 # Software injection based test cases: test cases are triggered via
 # mce-inject tool.
diff --git a/testcases/mce-test/config/simple_nopanic_noser.conf b/testcases/mce-test/config/simple_nopanic_noser.conf
index 7d1a5d3..835d9e6 100644
--- a/testcases/mce-test/config/simple_nopanic_noser.conf
+++ b/testcases/mce-test/config/simple_nopanic_noser.conf
@@ -1,4 +1,4 @@
 
-CASES="soft-inj/non-panic/cases.sh"
+CASES="soft-inj/non-panic/cases.sh soft-inj/poll_noser/cases.sh"
 GCOV=1
 KSRC_DIR=/lib/modules/$(uname -r)/build
diff --git a/testcases/mce-test/config/simple_noser.conf b/testcases/mce-test/config/simple_noser.conf
index e9c6e1a..b562070 100644
--- a/testcases/mce-test/config/simple_noser.conf
+++ b/testcases/mce-test/config/simple_noser.conf
@@ -1,4 +1,4 @@
 
-CASES="soft-inj/non-panic/cases.sh soft-inj/panic/cases.sh soft-inj/panic_npcc/cases.sh soft-inj/panic_noser/cases.sh"
+CASES="soft-inj/non-panic/cases.sh soft-inj/panic/cases.sh soft-inj/panic_npcc/cases.sh soft-inj/panic_noser/cases.sh soft-inj/poll_noser/cases.sh"
 GCOV=1
 KSRC_DIR=/lib/modules/$(uname -r)/build
diff --git a/testcases/mce-test/doc/howto.txt b/testcases/mce-test/doc/howto.txt
index d8b1235..418e728 100644
--- a/testcases/mce-test/doc/howto.txt
+++ b/testcases/mce-test/doc/howto.txt
@@ -26,7 +26,7 @@
 
   CONFIG_X86_MCE=y
   CONFIG_X86_MCE_INTEL=y
-  CONFIG_X86_MCE_INJECT=y
+  CONFIG_X86_MCE_INJECT=y or CONFIG_X86_MCE_INJECT=m
 
 - Get mcelog git version from 
   git://git.kernel.org/pub/scm/utils/cpu/mce/mcelog.git.
@@ -45,7 +45,14 @@
   make
   sudo make install
 
-- Run make test-simple
+- Install page-types tool (sec 3.4), which is accompanied with Linux kernel
+  source (2.6.32 or newer).
+
+  cd $KERNEL_SRC/Documentation/vm/
+  gcc -o page-types page-types.c
+  cp page-types /usr/bin/
+
+- Run make test
   This will do the basic tests, but not the more complicated kdump ones.
   For more information on those read below.
 
@@ -101,14 +108,13 @@
 				case trigger and test case verify, some
 				context has been gone.
 
-Several test case classes are provided with the test suite. They are
-all based on mce-inject MCE software injection tool, and follows same
-structure.
+Several test case classes are provided with the test suite. 
+cases/soft-inj/* is based on mce-inject MCE software injection tool.
+cases/apei-inj/* is based on apei-inj APEI haredware injection tool.
 
-cases/soft-inj/<class name>/cases.sh	Interface of the test case class
-cases/soft-inj/<class name>/data/	Directory contains data file for
-					mce-inject tool.
-cases/soft-inj/<class name>/refer/	Directory contains data file for
+cases/<injection tool>/<class name>/cases.sh	Interface of the test case class
+cases/<injection tool>/<class name>/data/	Directory contains data file
+cases/<injection tool>/<class name>/refer/	Directory contains data file for
 					reference MCE records if necessary.
 
 For document of various test cases, please refer to doc/cases/*.
@@ -169,13 +175,13 @@
 "results/<driver_name>/<case_name>/<xxx>. For in-package test case
 class, additional test results include:
 
-results/<driver_name>/soft-inject/<case_name>/klog
+results/<driver_name>/<injection_tool>/<case_name>/klog
 				Kernel log during testing
-results/<driver_name>/soft-inject/<case_name>/mcelog
+results/<driver_name>/<injection_tool>/<case_name>/mcelog
 				mcelog output during testing
-results/<driver_name>/soft-inject/<case_name>/mcelog_refer
+results/<driver_name>/<injection_tool>/<case_name>/mcelog_refer
 				mcelog output reference
-results/<driver_name>/soft-inject/<case_name>/mce_64.c.gcov (for gcov)
+results/<driver_name>/<injection_tool>/<case_name>/mce_64.c.gcov (for gcov)
 				gcov output file
 
 
@@ -214,6 +220,10 @@
 document. The latest gcovdump can be gotten from cvs:
 http://ltp.cvs.sourceforge.net/viewvc/ltp/utils/analysis/gcov-kdump/.
 
+3.4 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).
+It is required for MCE apei-inj testing. 
 
 4. Usage Guide
 --------------
@@ -241,6 +251,7 @@
    - A Linux kernel with full MCE injection support (see 0)
    - mce-inject tool (see 3.1)
    - mcelog with proper version (see 3.2)
+   - page-types (see 3.4)
 
 b. Modify config/simple.conf or create a new test configuration
    file. Refer to section 2.3 for more instruction about test
@@ -248,12 +259,19 @@
 
 c. Run "make". Carefully check for any errors.
 
-d. To be root and invoke simple test driver on test configuration file
+d. It is recommended to stop cron before testing. Because there
+   might be another mcelog reading events running on background
+   by cron, which will upset the test.
+
+      /etc/init.d/crond stop
+
+e. To be root and invoke simple test driver on test configuration file
    as follow
 
-       drivers/simple/driver.sh config/simple.conf
+       Run "make test" to do all the standard tests that do not require
+       special set up.
 
-e. General test result will go results/simple/result. Test log will go
+f. General test result will go results/simple/result. Test log will go
    work/simple/log. Additional test results for various test cases
    will go results/simple/<test case>/<xxx>. For more details about
    in-package test case class, please refer to section 2.1.
@@ -306,24 +324,48 @@
      * kexec-tools
      * kernel-devel
 
-c. In addition to bzImage and modules of Linux kernel should be
+c. Configure where to put the kdump /proc/vmcore files. The path should be
+   specified via COREDIR in test configuration file.
+   By default, the kdump /proc/vmcore files will be put into /var/crash.
+
+   For SLES10 or OpenSUSE Distro:
+     * edit KDUMP_SAVEDIR in /etc/sysconfig/kdump
+   For RHEL5 or Fedora distro:
+     * edit path in /etc/kdump.conf
+
+d. In addition to bzImage and modules of Linux kernel should be
    installed on test machine, the vmlinux of Linux kernel should be
    put on test machine and specified via VMLINUX in test configuration
    file.
 
-d. Make sure the partition where the test driver is running has space
+e. Make sure the partition where the test driver is running has space
    for the tests results and one vmcore file (size of physical
    memory).
 
-e. Create a new test configuration file or use a existing one in
+f. Now, reboot system. Test if kdump works by starting kdump and triggering
+   kernel panic.
+
+   For SLES10 or OpenSUSE Distro:
+    service boot.kdump restart
+    chkconfig boot.kdump on
+    echo "c" > /proc/sysrq-trigger
+
+   For RHEL5 or Fedora distro:
+    service kdump restart
+    /sbin/chkconfig kdump on
+    echo "c" > /proc/sysrq-trigger
+
+   After system reboot, check if there are vmcore files. By default, they are in /var/crash/*/. If yes, "kdump" works in the system.
+
+g. Create a new test configuration file or use a existing one in
    config/, such as kdump.conf. Note: not all test case classes can be
    used with kdump test driver, see "important points" below.
 
-f. Run "make". Carefully check for any errors.
+h. Run "make". Carefully check for any errors.
 
-g. To be root and run "drivers/kdump/driver.sh <conf>"
+i. To be root and run "drivers/kdump/driver.sh <conf>" or "make test-kdump" (for a full test)
 
-h. After test is done, the test log of the last run of kdump driver will
+j. After test is done, the test log of the last run of kdump driver will
    be displayed on main console.
 
 Few Important points to remember:
@@ -437,6 +479,15 @@
 
   Where <grep options> are same as options available to /bin/grep.
 
+- tools/loop-mce-test
+
+  Run mce test cases in a loop. It exits on failure of any one of the test
+  cases. This script is using simple test driver.
+
+  Usage:
+      ./loop-mce-test <config_file>
+ 
+  Note that only simple test configure file can be used here.
 
 5. Add test cases
 -----------------
diff --git a/testcases/mce-test/drivers/kdump/driver.sh b/testcases/mce-test/drivers/kdump/driver.sh
index f5982ec..6016582 100755
--- a/testcases/mce-test/drivers/kdump/driver.sh
+++ b/testcases/mce-test/drivers/kdump/driver.sh
@@ -1,4 +1,4 @@
-#!/bin/sh -xe
+#!/bin/bash -xe
 #
 # Kdump test driver: test case will trigger panic, and then crash
 # dump. The test result is collected via dumped vmcore. For more
@@ -33,7 +33,7 @@
     # crontab in some distros will not read from STDIN.
 
     cat <<EOF > $WDIR/kdump.cron
-SHELL=/bin/sh
+SHELL=/bin/bash
 PATH=/usr/local/bin:/usr/bin:/usr/sbin:/sbin:/bin
 MAILTO=root
 @reboot cd "$(pwd)"; ${0} $conf >> $WDIR/log 2>&1; cat $WDIR/log > /dev/console
@@ -63,16 +63,24 @@
 setup_kdump ()
 {
     echo "Start kdump daemon."
-    /etc/init.d/kdump restart
+
+    if [ -f /etc/init.d/kdump ]; then
+	    daemon=kdump
+    else
+	    #SLE11
+	    daemon=boot.kdump
+    fi
+
+    /etc/init.d/"${daemon}" restart
 
     echo "Enable kdump daemon by default."
     # Red Hat and SUSE.
     if [ -x "/sbin/chkconfig" ]; then
-        /sbin/chkconfig kdump on
+        /sbin/chkconfig "${daemon}" on
 
     # Debian and Ubuntu.
     elif [ -x "/sbin/update-rc.d" ]; then
-        /sbin/update-rc.d kdump defaults
+        /sbin/update-rc.d "${daemon}" defaults
     fi
 }
 
@@ -101,8 +109,9 @@
 	return
     fi
     if ! chk_gcov; then
-	echo "gcov is not supported by kernel, or there is no " \
-	    "gcov utility installed, disable gcov support."
+	echo "gcov is not supported by kernel or there is no " \
+	    "gcov utility installed"
+	echo "disabling gcov support"
 	unset GCOV
 	return
     fi
@@ -223,6 +232,15 @@
     exit -1
 fi
 
+#if mce_inject is a module, it is ensured to have been loaded
+if modinfo mce_inject > /dev/null 2>&1; then
+    if ! lsmod | grep -q mce_inject; then
+        if ! modprobe mce_inject; then
+	    die "module mce_inject isn't supported ?"
+        fi
+    fi
+fi
+
 for case_sh in ${CASES}; do
     for this_case in $($CDIR/$case_sh enumerate); do
 	export this_case
diff --git a/testcases/mce-test/drivers/kdump/setup.sh b/testcases/mce-test/drivers/kdump/setup.sh
index 4a61f04..f90742c 100755
--- a/testcases/mce-test/drivers/kdump/setup.sh
+++ b/testcases/mce-test/drivers/kdump/setup.sh
@@ -1,4 +1,4 @@
-#!/bin/sh -ex
+#!/bin/bash -ex
 #
 # Setup for kdump test driver.
 #
diff --git a/testcases/mce-test/drivers/simple/driver.sh b/testcases/mce-test/drivers/simple/driver.sh
index 8ba21ed..ebc9d2a 100755
--- a/testcases/mce-test/drivers/simple/driver.sh
+++ b/testcases/mce-test/drivers/simple/driver.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/bin/bash
 #
 # Simple test driver: run test cases one by one, assuming test case
 # will not trigger panic or reboot.
@@ -58,12 +58,21 @@
 	    export GCOV=copy
 	    export KSRC_DIR
 	else
-	    echo "gcov is not supported by kernel, or there is no " \
-		"gcov utility installed, disable gcov support."
+	    echo "gcov is not supported by kernel or there is no " \
+		"gcov utility installed"
+	    echo "disabling gcov support."
 	    unset GCOV
 	fi
     fi
 
+    #if mce_inject is a module, it is ensured to have been loaded
+    modinfo mce_inject > /dev/null 2>&1
+    if [ $? -eq 0 ]; then
+        lsmod | grep mce_inject > /dev/null 2>&1
+        [ $? -eq 0 ] || modprobe mce_inject
+        [ $? -eq 0 ] || die "module mce_inject isn't supported ?"
+    fi
+
     for case_sh in $CASES; do
 	for this_case in $($CDIR/$case_sh enumerate); do
 	    set_fake_panic 1
@@ -110,6 +119,9 @@
     start_background
 fi
 
+[ -d $RDIR ] && mv $RDIR --backup=numbered -T $RDIR.old
+[ -d $WDIR ] && mv $WDIR --backup=numbered -T $WDIR.old
+
 test_all
 
 if [ -n "$STOP_BACKGROUND" ]; then
diff --git a/testcases/mce-test/lib/dirs.sh b/testcases/mce-test/lib/dirs.sh
index 5228f16..9ca42b2 100755
--- a/testcases/mce-test/lib/dirs.sh
+++ b/testcases/mce-test/lib/dirs.sh
@@ -19,3 +19,4 @@
 RDIR=$ROOT/results/$driver
 WDIR=$ROOT/work/$driver
 LDIR=$ROOT/lib
+TDIR=$ROOT/tools
diff --git a/testcases/mce-test/lib/mce.sh b/testcases/mce-test/lib/mce.sh
index a9e70c4..39eb3a8 100755
--- a/testcases/mce-test/lib/mce.sh
+++ b/testcases/mce-test/lib/mce.sh
@@ -298,8 +298,25 @@
     cat /sys/devices/system/machinecheck/machinecheck0/tolerant
 }
 
+check_debugfs()
+{
+	mount|grep /sys/kernel/debug > /dev/null 2>&1
+	[ ! $? -eq 0 ] && mount -t debugfs none /sys/kernel/debug
+	mount|grep /sys/kernel/debug > /dev/null 2>&1
+	[ ! $? -eq 0 ] && die "Kernel without debugfs support ?"
+}
+
+# should be called after check_debugfs
+check_mce()
+{
+    DEBUGFS=`mount | grep debugfs | cut -d ' ' -f3 | head -1`
+    [ ! -d ${DEBUGFS}/mce ] && die "Kernel without CONFIG_X86_MCE_INJECT ?"
+}
+
 set_fake_panic()
 {
+    check_debugfs
+    check_mce
     [ $# -eq 1 ] || die "missing parameter for set_fake_panic"
     echo -n $1 > /sys/kernel/debug/mce/fake_panic
 }
diff --git a/testcases/mce-test/tools/Makefile b/testcases/mce-test/tools/Makefile
index 00e16fb..42afa1c 100644
--- a/testcases/mce-test/tools/Makefile
+++ b/testcases/mce-test/tools/Makefile
@@ -1,4 +1,7 @@
 
 all:
+	$(MAKE) -C simple_process
+	$(MAKE) -C simple_process install
 clean:
-distclean:
+	$(MAKE) -C simple_process clean
+distclean: clean
diff --git a/testcases/mce-test/tools/grep_result.sh b/testcases/mce-test/tools/grep_result.sh
index 4e044e8..4ef74ad 100755
--- a/testcases/mce-test/tools/grep_result.sh
+++ b/testcases/mce-test/tools/grep_result.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/bin/bash
 #
 # Filter out specified test case results from all results.
 #
diff --git a/testcases/mce-test/tsrc/Makefile b/testcases/mce-test/tsrc/Makefile
index 7cd1600..5b10e9a 100644
--- a/testcases/mce-test/tsrc/Makefile
+++ b/testcases/mce-test/tsrc/Makefile
@@ -5,11 +5,19 @@
 
 KFLAGS := -I ./kinclude
 
+EXE := tinjpage tsimpleinj tkillpoison tprctl tsoft tsoftinj thugetlb
+EXEKERNEL := tring ttable
+
+OBJ := $(addsuffix .o,${EXE})
+OBJKERNEL := $(addsuffix .o,${EXEKERNEL})
+
+.PHONY: clean distclean see test hard soft standalone
+
 all: standalone
 
-standalone: tinjpage tinjpage-working tkillpoison
+standalone: ${EXE}
 
-requireskernel: tcases ttable
+kernel: ${EXEKERNEL}
 
 tcases: tcases.c ${LSRC}/arch/x86/kernel/cpu/mcheck/mce-severity.c ${LSRC}/arch/x86/kernel/cpu/mcheck/mce-internal.h
 	${CC} ${CFLAGS} ${KFLAGS} -o tcases tcases.c
@@ -17,6 +25,8 @@
 ttable: ttable.c ${LSRC}/arch/x86/kernel/cpu/mcheck/mce-severity.c ${LSRC}/arch/x86/kernel/cpu/mcheck/mce-internal.h
 	${CC} ${CFLAGS} ${KFLAGS} -o ttable ttable.c
 
+tprctl: tprctl.o
+
 tring: tring.o 
 
 tring : LDFLAGS += -lpthread
@@ -34,9 +44,29 @@
 .PHONY: clean distclean
 
 clean:
-	rm -f tcases ttable x.html tinjpage	
-	rm -f tkillpoison tring
+	rm -f ${EXE} ${OBJ}
+	rm -f ${EXEKERNEL} ${OBJKERNEL}
+	rm -f x.html unpoison-failed offlined
+	rm -f ~test* ~poison*
 
 distclean: clean
 
+test: soft hard
+
+hard: standalone
+	./tinjpage
+	./tsimpleinj
+	if ! ./tkillpoison ; then echo "killed as expected" ; exit 0 ; else echo "didn't get killed" ; exit 1 ; fi
+	./tprctl
+
+soft: standalone
+	./tsoft
+	./tsoftinj
+	echo "Running soft offliner for 60 seconds"
+	./random_offline -t 60
+
+test-kernel: tcases
+	./tcases
+
+
 
diff --git a/testcases/mce-test/tsrc/README b/testcases/mce-test/tsrc/README
index e7fc32f..015f9e7 100644
--- a/testcases/mce-test/tsrc/README
+++ b/testcases/mce-test/tsrc/README
@@ -1,6 +1,10 @@
 These are some standalone test programs for various parts of the
 machine check code:
 
+They can be all tested together by running "make test"
+This requires root rights and a kernel with soft offlining and hard
+offlining support.
+
 To use ttable and tcases you need to specify a linux source tree
 with the mce improvements patchkit added with make LSRC=/path/to/linux
 or symlink the linux tree to ../linux
diff --git a/testcases/mce-test/tsrc/tinjpage-working.c b/testcases/mce-test/tsrc/tinjpage-working.c
index f217fec..e69de29 100644
--- a/testcases/mce-test/tsrc/tinjpage-working.c
+++ b/testcases/mce-test/tsrc/tinjpage-working.c
@@ -1,151 +0,0 @@
-/* 
- * Test program for Linux memory error recovery. 
- * Requires special injection support.
- */
-#define _GNU_SOURCE 1
-#include <sys/mman.h>
-#include <stdio.h>
-#include <signal.h>
-#include <unistd.h>
-#include <sys/fcntl.h>
-#include <stdlib.h>
-#include <setjmp.h>
-#include <errno.h>
-#include <string.h>
-
-#define MADV_POISON 100
-
-#define err(x) perror(x),exit(1)
-
-int count = 20;
-sigjmp_buf recover;
-int PS;
-
-void sighandler(int sig, siginfo_t *si, void *arg)
-{
-	printf("signal %d code %d addr %p\n", sig, si->si_code, si->si_addr);
-
-	if (--count == 0)
-		exit(1);
-
-	siglongjmp(recover, 1);
-}
-
-void testmem(char *msg, char *page, int write)
-{
-	printf("%s page %p\n", msg, page);
-	if (sigsetjmp(recover,1) == 0) {
-		if (madvise(page, PS, MADV_POISON) != 0)
-			perror("madvise");
-		if (write)
-			*page = 2;
-		else
-			printf("%x\n", *(unsigned char *)page);	
-	}
-	printf("recovered\n");
-}
-
-void expecterr(char *msg, int res)
-{
-	if (res == 0)
-		printf("no error on %s\n", msg);
-	else
-		perror(msg);
-}
-
-int tempfd(void)
-{
-	static int tmpcount;
-	int fd;
-	char buf[30];
-	snprintf(buf,30,"/tmp/test%d.XXXXXXXX",tmpcount++);
-	fd = mkstemp(buf);
-	if (fd >= 0)
-		unlink(buf);
-	return fd;
-}
-
-#define RANDOM_FILE "/etc/profile"
-
-int main(void)
-{
-	PS = getpagesize();
-	char *page;
-
-	struct sigaction sa = { 	
-		.sa_sigaction = sighandler,
-		.sa_flags = SA_SIGINFO
-	};
-	sigaction(SIGBUS, &sa, NULL);
-//	sigaction(SIGSEGV, &sa, NULL);
-
- 	page = mmap(NULL, PS, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_POPULATE, 0, 0);
-	testmem("dirty", page, 1);
-
-	page = mmap(NULL, PS, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_LOCKED, 0, 0);
-	testmem("mlocked", page, 1);
-
-	int fd = open(RANDOM_FILE, O_RDONLY);
-	if (fd < 0) err("open " RANDOM_FILE);
-	page = mmap(NULL, PS, PROT_READ, MAP_SHARED|MAP_POPULATE, fd, 0);
-	if (page == (char *)-1) err("mmap");
-	close(fd);
-	testmem("clean file", page, 0);
-
-	fd = tempfd();
-	if (fd < 0) err("open testfile");
-	char *tmp = malloc(PS);
-	if (!tmp) exit(ENOMEM);
-	memset(tmp, 0xff, PS);
-	write(fd, tmp, PS);
-	free(tmp);
-	page = mmap(NULL, PS, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
-	if (page == (char*)-1) err("mmap");
-	*page = 1;
-	testmem("file dirty", page, 0);
-	expecterr("msync expect error", msync(page, PS, MS_SYNC));
-	expecterr("fsync expect error", fsync(fd));
-	close(fd);
-
-	/* hole case still broken in the kernel -- doesn't report error */
-	fd = tempfd();
-	if (fd < 0) err("open testfile");
-	ftruncate(fd, PS);
-	page = mmap(NULL, PS, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
-	if (page == (char*)-1) err("mmap");
-	*page = 1;
-	testmem("hole file dirty", page, 0);
-	expecterr("hole msync expect error", msync(page, PS, MS_SYNC));
-	expecterr("hole fsync expect error", fsync(fd));
-	close(fd);
-
-#if 0
-	const int NPAGES = 10;
-	int i;
-	fd = tempfd();
-	if (fd < 0) err("open rfp testfile");
-	tmp = malloc(PS);
-	if (!tmp) exit(ENOMEM);
-	for (i = 0; i < NPAGES; i++)  {
-		memset(tmp, i, PS);
-		write(fd, tmp, PS);
-	}
-	free(tmp);
-	page = mmap(NULL, PS*NPAGES, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
-	if (page == (char*)-1) err("mmap");
-	int k = NPAGES - 1;
-	for (i = 0; i < NPAGES; i++, k--) {
-		if (remap_file_pages(page + i*PS, PS, 0, k, 0))
-			perror("remap_file_pages");
-	}
-	*page = 1;
-	testmem("rfp file dirty", page, 0);
-	expecterr("rfp msync expect error", msync(page, PS, MS_SYNC));
-	expecterr("rfp fsync expect error", fsync(fd));
-	close(fd);
-#endif
-
-	return 0;
-}	
-
-
diff --git a/testcases/mce-test/tsrc/tinjpage.c b/testcases/mce-test/tsrc/tinjpage.c
index 9300cb7..bee38af 100644
--- a/testcases/mce-test/tsrc/tinjpage.c
+++ b/testcases/mce-test/tsrc/tinjpage.c
@@ -2,7 +2,24 @@
  * Test program for Linux poison memory error recovery.
  * This injects poison into various mapping cases and triggers the poison
  * handling.  Requires special injection support in the kernel.
- * Author: Andi Kleen
+ * 
+ * Copyright 2009, 2010 Intel Corporation
+ *
+ * tinjpage 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.
+ *
+ * tinjpage 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 
+ *
+ * Authors: Andi Kleen, Fengguang Wu
  */
 #define _GNU_SOURCE 1
 #include <stdio.h>
@@ -17,15 +34,17 @@
 #include <string.h>
 #include <time.h>
 #include <pthread.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <sys/sem.h>
+#include "utils.h"
+#include "hugepage.h"
 
-#ifndef MADV_POISON
 #define MADV_POISON 100
-#endif
 
 #define TMPDIR "./"
 #define PATHBUFLEN 100
 
-#define err(x) perror(x),exit(1)
 #define Perror(x) failure++, perror(x)
 #define PAIR(x) x, sizeof(x)-1
 #define mb() asm volatile("" ::: "memory")
@@ -35,10 +54,13 @@
 #define cpu_relax() mb()
 #endif
 
+typedef unsigned long long u64;
+
 int PS;
 int failure;
 int unexpected;
 int early_kill;
+int test_hugepage;
 
 void *checked_mmap(void *start, size_t length, int prot, int flags,
                    int fd, off_t offset)
@@ -51,8 +73,10 @@
 
 void munmap_reserve(void *page, int size)
 {
-	munmap(page, size);
-	mmap(page, size, PROT_NONE, MAP_PRIVATE|MAP_FIXED, 0, 0);
+	if (munmap(page, size) < 0)
+		err("munmap");
+	if (mmap(page, size, PROT_NONE, MAP_PRIVATE|MAP_FIXED, 0, 0) < 0)
+		err("mmap2");
 }
 
 void *xmalloc(size_t s)
@@ -63,11 +87,40 @@
 	return p;
 }
 
+static int ilog2(int n)
+{
+	int r = 0;
+	n--;
+	while (n) {
+		n >>= 1;
+		r++;
+	}
+	return r;
+}
+
 int recovercount;
 sigjmp_buf recover_ctx;
 sigjmp_buf early_recover_ctx;
 void *expected_addr;
 
+/* Work around glibc not defining this yet */
+struct my_siginfo {
+	int si_signo;
+	int si_errno;
+	int si_code;
+	union {
+	struct {
+		void  *_addr; /* faulting insn/memory ref. */
+#ifdef __ARCH_SI_TRAPNO
+		int _trapno;	/* TRAP # which caused the signal */
+#endif
+		short _addr_lsb; /* LSB of the reported address */
+	} _sigfault;
+	} _sifields;
+};
+#undef si_addr_lsb
+#define si_addr_lsb _sifields._sigfault._addr_lsb
+
 void sighandler(int sig, siginfo_t *si, void *arg)
 {
 	if (si->si_addr != expected_addr) {
@@ -76,7 +129,18 @@
 		failure++;
 	}
 
-	printf("signal %d code %d addr %p\n", sig, si->si_code, si->si_addr);
+	int lsb = ((struct my_siginfo *)si)->si_addr_lsb;
+	if (test_hugepage) {
+		if (lsb != ilog2(HPS)) {
+			printf("LATER: Unexpected addr lsb in siginfo %d\n", lsb);
+		}
+	} else {
+		if (lsb != ilog2(sysconf(_SC_PAGE_SIZE))) {
+			printf("LATER: Unexpected addr lsb in siginfo %d\n", lsb);
+		}
+	}
+
+	printf("\tsignal %d code %d addr %p\n", sig, si->si_code, si->si_addr);
 
 	if (--recovercount == 0) {
 		write(1, PAIR("I seem to be in a signal loop. bailing out.\n"));
@@ -97,22 +161,79 @@
 	MNOTHING = -1,
 };
 
+void inject_madvise(char *page)
+{
+	if (madvise(page, PS, MADV_POISON) != 0) {
+		if (errno == EINVAL) {
+			printf("Kernel doesn't support poison injection\n");
+			exit(0);
+		}
+		Perror("madvise");
+	}
+}
+
+u64 page_to_pfn(char *page)
+{
+	static int pagemap_fd = -1;
+	u64 pfn;
+
+	if (pagemap_fd < 0)  {
+		pagemap_fd = open("/proc/self/pagemap", O_RDONLY); 
+		if (pagemap_fd < 0)
+			err("/proc/self/pagemap not supported");
+	}
+
+	if (pread(pagemap_fd, &pfn, sizeof(u64), 
+		((u64)page / PS)*sizeof(u64)) != sizeof(u64))
+		err("Cannot read from pagemap");
+
+	pfn &= (1ULL<<56)-1; 
+	return pfn;
+}
+
+/* 
+ * Inject Action Optional #MC 
+ * with mce-inject using the software injector.
+ * 
+ * This tests the low level machine check handler too.
+ * 
+ * Slightly racy with page migration because we don't mlock the page.
+ */
+void inject_mce_inject(char *page)
+{
+	u64 pfn = page_to_pfn(page);
+	FILE *mce_inject;
+
+	mce_inject = popen("mce-inject", "w");
+	if (!mce_inject) {
+		fprintf(stderr, "Cannot open pipe to mce-inject: %s\n",
+				strerror(errno));
+		exit(1);
+	}
+
+	fprintf(mce_inject, 
+		"CPU 0 BANK 3 STATUS UNCORRECTED SRAO 0xc0\n"
+		"MCGSTATUS RIPV MCIP\n"
+		"ADDR %#llx\n"
+		"MISC 0x8c\n"
+		"RIP 0x73:0x1eadbabe\n", pfn);
+
+	if (ferror(mce_inject) || fclose(mce_inject) < 0) { 
+		fprintf(stderr, "mce-inject failed: %s\n", strerror(errno));
+		exit(1);
+	} 
+}
+
+void (*inject)(char *page) = inject_madvise;
+
 void poison(char *msg, char *page, enum rmode mode)
 {
 	expected_addr = page;
 	recovercount = 5;
 
 	if (sigsetjmp(early_recover_ctx, 1) == 0) {
-
-		if (madvise(page, PS, MADV_POISON) != 0) {
-			if (errno == EINVAL) {
-				printf("Kernel doesn't support poison injection\n");
-				exit(0);
-			}
-			Perror("madvise");
-			return;
-		}
-
+		inject(page);
+		
 		if (early_kill && (mode == MWRITE || mode == MREAD)) {
 			printf("XXX: %s: process is not early killed\n", msg);
 			failure++;
@@ -126,7 +247,7 @@
 			printf("XXX: %s: killed\n", msg);
 			failure++;
 		} else
-			printf("recovered\n");
+			printf("\trecovered\n");
 	}
 }
 
@@ -138,18 +259,18 @@
 	if (sigsetjmp(recover_ctx, 1) == 0) {
 		switch (mode) {
 		case MWRITE:
-			printf("writing 2\n");
+			printf("\twriting 2\n");
 			*page = 2;
 			break;
 		case MWRITE_OK:
-			printf("writing 4\n");
+			printf("\twriting 4\n");
 			*page = 4;
 			return;
 		case MREAD:
-			printf("%x\n", *(unsigned char *)page);
+			printf("\treading %x\n", *(unsigned char *)page);
 			break;
 		case MREAD_OK:
-			printf("%x\n", *(unsigned char *)page);
+			printf("\treading %x\n", *(unsigned char *)page);
 			return;
 		case MNOTHING:
 			return;
@@ -163,12 +284,12 @@
 		printf("XXX: %s: killed\n", msg);
 		failure++;
 	} else
-		printf("recovered\n");
+		printf("\trecovered\n");
 }
 
 void testmem(char *msg, char *page, enum rmode mode)
 {
-	printf("%s page %p\n", msg, page);
+	printf("\t%s poisoning page %p\n", msg, page);
 	poison(msg, page, mode);
 	recover(msg, page, mode);
 }
@@ -176,20 +297,24 @@
 void expecterr(char *msg, int err)
 {
 	if (err) {
-		printf("expected error %d on %s\n", errno, msg);
+		printf("\texpected error %d on %s\n", errno, msg);
 	} else {
 		failure++;
 		printf("XXX: unexpected no error on %s\n", msg);
 	}
 }
 
+/* 
+ * Any optional error is really a deficiency in the kernel VFS error reporting
+ * and should be eventually fixed and turned into a expecterr
+ */
 void optionalerr(char *msg, int err)
 {
 	if (err) {
-		printf("expected optional error %d on %s\n", errno, msg);
+		printf("\texpected optional error %d on %s\n", errno, msg);
 	} else {
 		unexpected++;
-		printf("XXX: expected likely incorrect no error on %s\n", msg);
+		printf("LATER: expected likely incorrect no error on %s\n", msg);
 	}
 }
 
@@ -198,7 +323,7 @@
 {
 	int fd;
 	char buf[PATHBUFLEN];
-	snprintf(buf, sizeof buf, TMPDIR "poison%d",tmpcount++);
+	snprintf(buf, sizeof buf, TMPDIR "~poison%d",tmpcount++);
 	fd = open(buf, O_CREAT|O_RDWR, 0600);
 	if (fd >= 0)
 		unlink(buf);
@@ -211,7 +336,7 @@
 {
 	int fd;
 	if (buf[0] == 0)
-		snprintf(buf, PATHBUFLEN, TMPDIR "poison%d", tmpcount++);
+		snprintf(buf, PATHBUFLEN, TMPDIR "~poison%d", tmpcount++);
 	fd = open(buf, O_CREAT|O_RDWR|O_TRUNC, 0600);
 	if (fd < 0)
 		err("opening temporary file in " TMPDIR);
@@ -249,54 +374,76 @@
 	testmem("mlocked", page, MWRITE);
 }
 
-static void file_clean(void)
+static void do_file_clean(int flags, char *name)
 {
 	char *page;
 	char fn[30];
-	snprintf(fn, 30, TMPDIR "test%d", tmpcount++);
+	snprintf(fn, 30, TMPDIR "~test%d", tmpcount++);
 	int fd = open(fn, O_RDWR|O_TRUNC|O_CREAT);
 	if (fd < 0)
 		err("open temp file");
 	write(fd, fn, 4);
+	page = checked_mmap(NULL, PS, PROT_READ|PROT_WRITE, MAP_SHARED|flags, 
+		fd, 0);
 	fsync(fd);
-	page = checked_mmap(NULL, PS, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
 	close(fd);
-	testmem("file clean", page, MREAD_OK);
-	printf("%x\n", *(unsigned char *)page); /* reread page from disk */
-	testmem("file clean", page, MWRITE_OK);
+	testmem(name, page, MREAD_OK);
+	 /* reread page from disk */
+	printf("\t reading %x\n", *(unsigned char *)page);	
+	testmem(name, page, MWRITE_OK);
 }
 
-static void file_dirty(void)
+static void file_clean(void)
 {
+	do_file_clean(0, "file clean");
+}
+
+static void file_clean_mlocked(void)
+{
+	do_file_clean(MAP_LOCKED, "file clean mlocked");
+}
+
+static char *ndesc(char *buf, char *name, char *add)
+{
+	snprintf(buf, 100, "%s %s", name, add);
+	return buf;
+}
+
+static void do_file_dirty(int flags, char *name)
+{
+	char nbuf[100];
 	char *page;
 	char fn[PATHBUFLEN];
 	fn[0] = 0;
 	int fd = playfile(fn);
 
-	page = checked_mmap(NULL, PS, PROT_READ, MAP_SHARED|MAP_POPULATE, fd, 0);
-	testmem("dirty file initial", page, MREAD);
+	page = checked_mmap(NULL, PS, PROT_READ, 
+			MAP_SHARED|MAP_POPULATE|flags, fd, 0);
+	testmem(ndesc(nbuf, name, "initial"), page, MREAD);
 	expecterr("msync expect error", msync(page, PS, MS_SYNC) < 0);
 	close(fd);
 	munmap_reserve(page, PS);
 
 	fd = open(fn, O_RDONLY);
 	if (fd < 0) err("reopening temp file");
-	page = checked_mmap(NULL, PS, PROT_READ, MAP_SHARED|MAP_POPULATE, fd, 0);
-	recover("dirty file populated", page, MREAD_OK);
+	page = checked_mmap(NULL, PS, PROT_READ, MAP_SHARED|MAP_POPULATE|flags, 
+				fd, 0);
+	recover(ndesc(nbuf, name, "populated"), page, MREAD_OK);
 	close(fd);
 	munmap_reserve(page, PS);
 
 	fd = open(fn, O_RDONLY);
 	if (fd < 0) err("reopening temp file");
-	page = checked_mmap(NULL, PS, PROT_READ, MAP_SHARED, fd, 0);
-	recover("dirty file fault", page, MREAD_OK);
+	page = checked_mmap(NULL, PS, PROT_READ, MAP_SHARED|flags, fd, 0);
+	recover(ndesc(nbuf, name, "fault"), page, MREAD_OK);
 	close(fd);
 	munmap_reserve(page, PS);
 
 	fd = open(fn, O_RDWR);
 	char buf[128];
-	expecterr("explicit read after poison", read(fd, buf, sizeof buf) < 0);
-	expecterr("explicit write after poison", write(fd, "foobar", 6) < 0);
+	/* the earlier close has eaten the error */
+	optionalerr("explicit read after poison", read(fd, buf, sizeof buf) < 0);
+	optionalerr("explicit write after poison", write(fd, "foobar", 6) < 0);
 	optionalerr("fsync expect error", fsync(fd) < 0);
 	close(fd);
 
@@ -305,6 +452,16 @@
 		perror("unlink");
 }
 
+static void file_dirty(void)
+{
+	do_file_dirty(0, "file dirty");
+}
+
+static void file_dirty_mlocked(void)
+{
+	do_file_dirty(MAP_LOCKED, "file dirty mlocked");
+}
+
 /* TBD */
 static void file_hole(void)
 {
@@ -315,7 +472,8 @@
 	page = checked_mmap(NULL, PS, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
 	*page = 1;
 	testmem("hole file dirty", page, MREAD);
-	expecterr("hole fsync expect error", fsync(fd) < 0);
+	/* hole error reporting doesn't work in kernel currently, so optional */
+	optionalerr("hole fsync expect error", fsync(fd) < 0);
 	optionalerr("hole msync expect error", msync(page, PS, MS_SYNC) < 0);
 	close(fd);
 }
@@ -348,6 +506,10 @@
 	close(fd);
 }
 
+/* 
+ * These tests are currently too racy to be enabled.
+ */
+
 /*
  * This is quite timing dependent. The sniper might hit the page
  * before it is dirtied. If that happens tweak the delay
@@ -443,6 +605,237 @@
 	close(fd);
 }
 
+/*
+ * semaphore get/put wrapper
+ */
+int get_semaphore(int sem_id, struct sembuf *sembuffer)
+{
+	sembuffer->sem_num = 0;
+	sembuffer->sem_op  = -1;
+	sembuffer->sem_flg = SEM_UNDO;
+	return semop(sem_id, sembuffer, 1);
+}
+
+int put_semaphore(int sem_id, struct sembuf *sembuffer)
+{
+	sembuffer->sem_num = 0;
+	sembuffer->sem_op  = 1;
+	sembuffer->sem_flg = SEM_UNDO;
+	return semop(sem_id, sembuffer, 1);
+}
+
+/* memory sharing mode */
+enum shared_mode {
+	MMAP_SHARED = 0,
+	IPV_SHARED  = 1,
+};
+
+/*
+ * testcase for shared pages, where
+ *  if early_kill == 0, parent access the shared page hwpoisoned by child, and
+ *  if early_kill == 1, parent will be killed by SIGBUS from child.
+ * This testcase checks whether if a shared page is hwpoisoned by one process,
+ * another process sharing the page will be killed expectedly.
+ */
+static void do_shared(int shared_mode)
+{
+	int shm_id = -1, sem_id = -1, semaphore;
+	pid_t pid;
+	char *shared_page = NULL;
+	struct sembuf sembuffer;
+
+	if (shared_mode == MMAP_SHARED) {
+		shared_page = checked_mmap(NULL, PS, PROT_READ|PROT_WRITE,
+				MAP_SHARED|MAP_ANONYMOUS|MAP_POPULATE, 0, 0);
+	} else if (shared_mode == IPV_SHARED) {
+		shm_id = shmget(IPC_PRIVATE, PS, 0666|IPC_CREAT);
+		if (shm_id == -1)
+			err("shmget");
+	} else {
+		printf("XXX: invalid shared_mode\n");
+		return;
+	}
+
+	if (early_kill) {
+		sem_id = semget(IPC_PRIVATE, 1, 0666|IPC_CREAT);
+		if (sem_id == -1) {
+			perror("semget");
+			goto cleanup;
+		}
+		semaphore = semctl(sem_id, 0, SETVAL, 1);
+		if (semaphore == -1) {
+			perror("semctl");
+			goto cleanup;
+		}
+		if (get_semaphore(sem_id, &sembuffer)) {
+			perror("get_semaphore");
+			goto cleanup;
+		}
+	}
+
+	pid = fork();
+	if (pid < 0) {
+		perror("fork");
+		goto cleanup;
+	}
+
+	if (shared_mode == IPV_SHARED) {
+		shared_page = shmat(shm_id, NULL, 0);
+		if (shared_page == (char *)-1) {
+			perror("shmat");
+			goto cleanup;
+		}
+	}
+
+	memset(shared_page, 'a', 3);
+
+	if (early_kill) {
+		struct sigaction sa = {
+			.sa_sigaction = sighandler,
+			.sa_flags = SA_SIGINFO
+		};
+		sigaction(SIGBUS, &sa, NULL);
+		expected_addr = shared_page;
+	}
+
+	if (pid) {
+		siginfo_t sig;
+
+		if (early_kill && sigsetjmp(early_recover_ctx, 1) == 0) {
+			if (put_semaphore(sem_id, &sembuffer))
+				err("get_semaphore");
+			/* waiting for SIGBUS from child */
+			sleep(10);
+			printf("XXX timeout: child process does not send signal\n");
+			failure++;
+			goto cleanup;
+		}
+		waitid(P_PID, pid, &sig, WEXITED);
+
+		/*
+		 * check child termination status
+		 * late kill       : child should exit
+		 * suicide version : child should be killed by signal
+		 * early kill      : child should be killed by signal
+		 */
+		if (!early_kill) {
+			struct sigaction sigact;
+			sigaction(SIGBUS, NULL, &sigact);
+
+			if (sigact.sa_handler == SIG_DFL) {/* suicide version */
+				if (sig.si_code != CLD_KILLED)
+					goto child_error;
+			} else { /* late kill */
+				if (sig.si_code != CLD_EXITED)
+					goto child_error;
+			}
+		} else { /* early kill */
+			if (sig.si_code != CLD_EXITED)
+				goto child_error;
+		}
+
+		if (!early_kill)
+			recover("ipv shared page (parent)",
+				shared_page, MWRITE);
+
+		if (shared_mode == IPV_SHARED && shmdt(shared_page) == -1) {
+			perror("shmdt");
+			goto cleanup;
+		}
+	}
+
+	if (!pid) {
+		failure = 0;
+
+		if (early_kill)
+			if (get_semaphore(sem_id, &sembuffer))
+				err("get_semaphore");
+		testmem("ipv shared page", shared_page, MWRITE);
+
+		if (shared_mode == IPV_SHARED && shmdt(shared_page) == -1)
+			err("shmdt");
+
+		fflush(stdout);
+		_exit(failure);
+	}
+
+cleanup:
+	if (shared_page) {
+		if (shared_mode == IPV_SHARED)
+			shmdt(shared_page);
+		else
+			munmap_reserve(shared_page, PS);
+	}
+	if (shm_id >= 0 && shmctl(shm_id, IPC_RMID, NULL) < 0) 
+		err("shmctl IPC_RMID");
+	if (sem_id >= 0 && semctl(sem_id, 0, IPC_RMID) < 0)
+		err("semctl IPC_RMID");
+	return;
+
+child_error:
+	printf("XXX child process was terminated unexpectedly\n");
+	failure++;
+	goto cleanup;
+}
+
+static void mmap_shared(void)
+{
+	do_shared(MMAP_SHARED);
+}
+
+static void ipv_shared(void)
+{
+	do_shared(IPV_SHARED);
+}
+
+static void anonymous_hugepage(void)
+{
+	char *page;
+	/* Hugepage isn't supported. */
+	if (!HPS)
+		return;
+	test_hugepage = 1;
+	page = alloc_anonymous_hugepage(HPS, 1);
+	/* prefault */
+	page[0] = 'a';
+	testmem("anonymous hugepage", page, MWRITE);
+	free_anonymous_hugepage(page, HPS);
+	test_hugepage = 0;
+}
+
+static void file_backed_hugepage(void)
+{
+	char *page;
+	char buf[PATHBUFLEN];
+	int fd;
+	/* Hugepage isn't supported. */
+	if (!HPS)
+		return;
+	test_hugepage = 1;
+	snprintf(buf, PATHBUFLEN, "%s/test%d", hugetlbfsdir, tmpcount++);
+	page = alloc_filebacked_hugepage(buf, HPS, 0, &fd);
+	/* prefault */
+	page[0] = 'a';
+	testmem("file backed hugepage", page, MWRITE);
+	free_filebacked_hugepage(page, HPS, fd, buf);
+	test_hugepage = 0;
+}
+
+static void shm_hugepage(void)
+{
+	char *page;
+	/* Hugepage isn't supported. */
+	if (!HPS)
+		return;
+	test_hugepage = 1;
+	page = alloc_shm_hugepage(&tmpcount, HPS);
+	/* prefault */
+	page[0] = 'a';
+	testmem("shared memory hugepage", page, MWRITE);
+	free_shm_hugepage(tmpcount, page);
+	tmpcount++;
+	test_hugepage = 0;
+}
 
 struct testcase {
 	void (*f)(void);
@@ -455,16 +848,58 @@
 	{ file_clean, "file clean", 1 },
 	{ file_dirty, "file dirty" },
 	{ file_hole, "file hole" },
+	{ file_clean_mlocked, "file clean mlocked", 1 },
+	{ file_dirty_mlocked, "file dirty mlocked"},
 	{ nonlinear, "nonlinear" },
-	/* { under_io_dirty, "under io dirty" }, */
-	/* { under_io_clean, "under io clean" }, */
+	{ mmap_shared, "mmap shared" },
+	{ ipv_shared, "ipv shared" },
+	{ anonymous_hugepage, "anonymous hugepage" },
+	{ file_backed_hugepage, "file backed hugepage" },
+	{ shm_hugepage, "shared memory hugepage" },
+	{},	/* dummy 1 for sniper */
+	{},	/* dummy 2 for sniper */
 	{}
 };
 
+struct testcase snipercases[] = {
+	{ under_io_dirty, "under io dirty" }, 
+	{ under_io_clean, "under io clean" },
+};
 
-int main(void)
+void usage(void)
 {
+	fprintf(stderr, "Usage: tinjpage [--sniper]\n"
+			"Test hwpoison injection on pages in various states\n"
+			"--mce-inject    Use mce-inject for injection\n"
+			"--sniper  Enable racy sniper tests (likely broken)\n");
+	exit(1);
+}
+
+void handle_opts(char **av)
+{
+	while (*++av) { 
+		if (!strcmp(*av, "--sniper")) { 
+			struct testcase *t;
+			for (t = cases; t->f; t++)
+				;
+			*t++ = snipercases[0];
+			*t++ = snipercases[1];
+		}
+		else if (!strcmp(*av, "--mce-inject")) { 
+			inject = inject_mce_inject;			
+		} else 
+			usage();
+	}
+}
+
+int main(int ac, char **av)
+{
+	if (av[1])
+		handle_opts(av);
+
 	PS = getpagesize();
+	if (hugetlbfs_root(hugetlbfsdir))
+		HPS = gethugepagesize();
 
 	/* don't kill me at poison time, but possibly at page fault time */
 	early_kill = 0;
@@ -478,11 +913,14 @@
 	struct testcase *t;
 	/* catch signals */
 	sigaction(SIGBUS, &sa, NULL);
-	for (t = cases; t->f; t++)
+	for (t = cases; t->f; t++) { 
+		printf("---- testing %s\n", t->name);
 		t->f();
+	}
 
 	/* suicide version */
 	for (t = cases; t->f; t++) {
+		printf("---- testing %s in child\n", t->name);
 		pid_t child = fork();
 		if (child == 0) {
 			signal(SIGBUS, SIG_DFL);
@@ -517,8 +955,10 @@
 	system("sysctl -w vm.memory_failure_early_kill=1");
 
 	sigaction(SIGBUS, &sa, NULL);
-	for (t = cases; t->f; t++)
+	for (t = cases; t->f; t++) {
+		printf("---- testing %s (early kill)\n", t->name);
 		t->f();
+	}
 
 	if (failure > 0) {
 		printf("FAILURE -- %d cases broken!\n", failure);
diff --git a/testcases/mce-test/tsrc/tkillpoison.c b/testcases/mce-test/tsrc/tkillpoison.c
index 328a5bb..ce99429 100644
--- a/testcases/mce-test/tsrc/tkillpoison.c
+++ b/testcases/mce-test/tsrc/tkillpoison.c
@@ -5,7 +5,7 @@
 #include <stdio.h>
 #include <unistd.h>
 
-#define MADV_POISON 12
+#define MADV_POISON 100
 
 int main(void)
 {
diff --git a/testcases/mce-test/tsrc/tring.c b/testcases/mce-test/tsrc/tring.c
index 0d57ef7..0ed14f5 100644
--- a/testcases/mce-test/tsrc/tring.c
+++ b/testcases/mce-test/tsrc/tring.c
@@ -1,4 +1,4 @@
-
+/* Unit tester for ring buffer code in mce.c */
 #define DEFINE_PER_CPU(a,b) a b
 #define __get_cpu_var(x) x
 #define barrier() asm volatile("" ::: "memory")
@@ -64,7 +64,7 @@
 	}
 }
 
-main()
+int main(void)
 {
 	long k;
 	
@@ -82,4 +82,6 @@
 			k++;
 		}
 	}
+
+	return 0;
 }
diff --git a/testcases/open_posix_testsuite/scripts/generate-makefiles.sh b/testcases/open_posix_testsuite/scripts/generate-makefiles.sh
index 536d407..ed6406f 100755
--- a/testcases/open_posix_testsuite/scripts/generate-makefiles.sh
+++ b/testcases/open_posix_testsuite/scripts/generate-makefiles.sh
@@ -152,11 +152,11 @@
 
 	fi
 
-	if [ "$tests" != "" ] && ! grep -q '^run.sh' "$makefile.3"; then
+	if ! grep -q '^run.sh' "$makefile.3"; then
 		cat >> "$makefile.3" <<EOF
 run.sh:
 	@echo '#/bin/sh' > \$@
-	@echo "\$(top_srcdir)/bin/run-tests.sh \$(subdir) $tests" >> \$@
+	@echo "\$(top_srcdir)/bin/run-tests.sh \$(subdir) \$(INSTALL_TARGETS)" >> \$@
 	@chmod +x run.sh
 
 EOF