diff options
author | Andi Kleen <ak@linux.intel.com> | 2009-10-08 08:22:18 +0200 |
---|---|---|
committer | Andi Kleen <ak@linux.intel.com> | 2009-10-08 08:22:18 +0200 |
commit | 6cb23d674850528c8337407c03e97bcd347ece93 (patch) | |
tree | 2984a395fb3131f9ac52513dbea6f1e1b8b6a71e | |
parent | 78fdb9f9d4a8c305fb5b82f317311fdc7621b555 (diff) | |
download | mce-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/Makefile | 4 | ||||
-rw-r--r-- | tsrc/tprctl.c | 96 |
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; +} |