aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndi Kleen <ak@linux.intel.com>2009-10-08 08:22:18 +0200
committerAndi Kleen <ak@linux.intel.com>2009-10-08 08:22:18 +0200
commit6cb23d674850528c8337407c03e97bcd347ece93 (patch)
tree2984a395fb3131f9ac52513dbea6f1e1b8b6a71e
parent78fdb9f9d4a8c305fb5b82f317311fdc7621b555 (diff)
downloadmce-test-6cb23d674850528c8337407c03e97bcd347ece93.tar.gz
Add prctl tester for hwpoison
(requires hwpoison-2.6.32) Signed-off-by: Andi Kleen <ak@linux.intel.com>
-rw-r--r--tsrc/Makefile4
-rw-r--r--tsrc/tprctl.c96
2 files changed, 99 insertions, 1 deletions
diff --git a/tsrc/Makefile b/tsrc/Makefile
index 7cd1600..77a5e6c 100644
--- a/tsrc/Makefile
+++ b/tsrc/Makefile
@@ -7,7 +7,7 @@ KFLAGS := -I ./kinclude
all: standalone
-standalone: tinjpage tinjpage-working tkillpoison
+standalone: tinjpage tinjpage-working tkillpoison tprctl
requireskernel: tcases ttable
@@ -17,6 +17,8 @@ tcases: tcases.c ${LSRC}/arch/x86/kernel/cpu/mcheck/mce-severity.c ${LSRC}/arch/
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
diff --git a/tsrc/tprctl.c b/tsrc/tprctl.c
new file mode 100644
index 0000000..51351a7
--- /dev/null
+++ b/tsrc/tprctl.c
@@ -0,0 +1,96 @@
+// test prctl per process setting
+#define _GNU_SOURCE 1
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/prctl.h>
+#include <setjmp.h>
+#include <signal.h>
+
+#define err(x) perror("FAILURE: " x), exit(1)
+#define fail(x) printf("FAILURE: " x "\n"), exit(1)
+#define mb() asm volatile("" ::: "memory")
+
+#define MADV_POISON 100
+
+/*
+ * Set early/late kill mode for hwpoison memory corruption.
+ * This influences when the process gets killed on a memory corruption.
+ */
+#define PR_MCE_KILL 33
+# define PR_MCE_KILL_CLEAR 0
+# define PR_MCE_KILL_SET 1
+
+# define PR_MCE_KILL_LATE 0
+# define PR_MCE_KILL_EARLY 1
+# define PR_MCE_KILL_DEFAULT 2
+
+#define PR_MCE_KILL_GET 34
+
+sigjmp_buf recover_ctx;
+volatile int seq;
+
+void handler(int sig)
+{
+ siglongjmp(recover_ctx, 1);
+}
+
+void test(int early)
+{
+ int PS = getpagesize();
+ char *ptr = mmap(NULL, PS, PROT_READ|PROT_WRITE,
+ MAP_PRIVATE|MAP_ANONYMOUS|MAP_POPULATE, 0,0);
+ if (ptr == (char *)-1L)
+ err("mmap");
+ signal(SIGBUS, handler);
+ printf("ptr = %p\n", ptr);
+ if (sigsetjmp(recover_ctx, 1) == 0) {
+ seq = 0;
+ printf("injection\n");
+ if (madvise(ptr, PS, MADV_POISON) < 0)
+ err("MADV_POISON");
+ /* early kill should kill here */
+ seq++;
+ mb();
+ printf("faulting\n");
+ /* late kill should kill here */
+ *ptr = 1;
+ printf("finished\n");
+ } else {
+ printf("recovered\n");
+ if (seq == 1 && !early)
+ fail("early mode set, but no early kill");
+ if (seq == 0 && early)
+ fail("late mode set, but early kill");
+ }
+}
+
+int main(void)
+{
+ int err;
+ err = prctl(PR_MCE_KILL_GET, 0, 0, 0, 0, 0);
+ if (err < 0)
+ err("PR_MCE_KILL_GET");
+ if (err != PR_MCE_KILL_DEFAULT)
+ fail("starting policy not default");
+ if (prctl(PR_MCE_KILL_SET, PR_MCE_KILL_SET, PR_MCE_KILL_LATE) < 0)
+ err("PR_MCE_KILL_SET late");
+ test(0);
+ if (prctl(PR_MCE_KILL_SET, PR_MCE_KILL_SET, PR_MCE_KILL_EARLY) < 0)
+ err("PR_MCE_KILL_SET early");
+ test(1);
+ err = prctl(PR_MCE_KILL_GET, 0, 0, 0,0,0);
+ if (err < 0)
+ err("PR_MCE_KILL_GET");
+ if (err != PR_MCE_KILL_EARLY)
+ fail("get mode not early after setting");
+ if (prctl(PR_MCE_KILL_SET, PR_MCE_KILL_CLEAR, 0, 0,0,0) < 0)
+ err("PR_MCE_KILL_CLEAR");
+ err = prctl(PR_MCE_KILL_GET, 0, 0, 0, 0, 0);
+ if (err < 0)
+ err("PR_MCE_KILL_GET");
+ if (err != PR_MCE_KILL_DEFAULT)
+ fail("ending policy not default");
+ return 0;
+}