aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndi Kleen <ak@linux.intel.com>2009-12-14 14:47:35 +0100
committerAndi Kleen <ak@linux.intel.com>2009-12-14 14:47:35 +0100
commit7ecd1b6daa8b40d866a7b98edc750988db210f8d (patch)
treed32c44819d5b7e236f083b4d8465da508495d9ce
parent3d35af8b3ea31539ce1c21664c54c024dd00a301 (diff)
downloadmce-test-7ecd1b6daa8b40d866a7b98edc750988db210f8d.tar.gz
Random soft offline test cases
Signed-off-by: Andi Kleen <ak@linux.intel.com>
-rw-r--r--tsrc/Makefile2
-rwxr-xr-xtsrc/random_offline71
-rw-r--r--tsrc/tsoft.c29
-rw-r--r--tsrc/tsoftinj.c129
4 files changed, 230 insertions, 1 deletions
diff --git a/tsrc/Makefile b/tsrc/Makefile
index 5f384d5..17da18d 100644
--- a/tsrc/Makefile
+++ b/tsrc/Makefile
@@ -5,7 +5,7 @@ CFLAGS += -I ${LSRC}/arch/x86/kernel/cpu/mcheck/ -g -Wall
KFLAGS := -I ./kinclude
-EXE := tinjpage tinjpage-working tkillpoison tprctl
+EXE := tinjpage tinjpage-working tkillpoison tprctl tsoft tsoftinj
EXEKERNEL := tring ttable
OBJ := $(addsuffix .o,${EXE})
diff --git a/tsrc/random_offline b/tsrc/random_offline
new file mode 100755
index 0000000..3386abc
--- /dev/null
+++ b/tsrc/random_offline
@@ -0,0 +1,71 @@
+#!/bin/bash
+# randomly soft offline pages
+
+# fixme: uses time seed, non reproducible
+
+#mount -t debugfs none /debug
+
+THRESH=${1:-1000}
+
+end_of_memory() {
+ for i in /sys/firmware/memmap/* ; do
+ case "$(< $i/type)" in
+ "System RAM") ;;
+ *) continue ;;
+ esac
+
+ k=$(< $i/end)
+ k=${k/0x/}
+ k=$(echo $k | tr a-z A-Z)
+
+ echo "ibase=16; $k/1000" | bc
+ done | sort -n | tail -n1
+}
+
+E=$(end_of_memory)
+
+echo "soft offlining pages upto $E"
+
+unpoison() {
+ if [ ! -f offlined ] ; then
+ return
+ fi
+
+ echo unpoisioning
+ while read i ; do
+ #echo -n ,
+ #echo "u $i"
+ echo $i | sed 's/000$//' > /debug/hwpoison/unpoison-pfn \
+ || echo "unpoisioning $i failed: $?"
+ done < offlined
+ echo done
+ echo
+}
+
+trap unpoison 0
+
+(( k = 0 ))
+rm -f offlined
+while true ; do
+ T=$(
+ R=$RANDOM
+ X=$(echo "obase=16; ($R%$E)*4096" | bc)
+ echo 0x$X
+ )
+ #echo "p $T"
+ if echo 2>/dev/null $T >/sys/devices/system/memory/soft_offline_page ; then
+ echo $T >> offlined
+ else
+ #echo offlining $T failed $?
+ true
+ fi
+ #echo -n .
+
+ (( k++ ))
+ if [ $k -gt $THRESH ] ; then
+ unpoison
+ (( k = 0 ))
+ rm offlined
+ fi
+done
+
diff --git a/tsrc/tsoft.c b/tsrc/tsoft.c
new file mode 100644
index 0000000..4fbaa15
--- /dev/null
+++ b/tsrc/tsoft.c
@@ -0,0 +1,29 @@
+/* Simplest soft offline testcase */
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#define err(x) perror(x), exit(1)
+
+#define MADV_SOFT_OFFLINE 101 /* soft offline page for testing */
+
+int PS;
+
+int main(void)
+{
+ PS = getpagesize();
+ char *map = mmap(NULL, PS, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, 0, 0);
+
+ if (map == (char *)-1L)
+ err("mmap");
+
+ *map = 1;
+
+ if (madvise(map, PS, MADV_SOFT_OFFLINE) < 0)
+ perror("madvise SOFT_OFFLINE");
+
+ *map = 2;
+
+ return 0;
+}
diff --git a/tsrc/tsoftinj.c b/tsrc/tsoftinj.c
new file mode 100644
index 0000000..e48c912
--- /dev/null
+++ b/tsrc/tsoftinj.c
@@ -0,0 +1,129 @@
+/* Test soft page offline for process pages using madvise injector */
+#define _GNU_SOURCE 1
+#include <sys/mman.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/fcntl.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#define MADV_SOFT_OFFLINE 101
+
+#define err(x) perror(x), exit(1)
+
+int PS;
+int exitcode;
+char empty[4096];
+int corrupted;
+
+void *checked_mmap(void *addr, size_t length, int prot, int flags,
+ int fd, off_t offset)
+{
+ void *p = mmap(addr, length, prot, flags, fd, offset);
+ if (p == (void *)-1L)
+ err("mmap");
+ return p;
+}
+
+unsigned meminfo(char *fmt)
+{
+ int found = 0;
+ FILE *f = fopen("/proc/meminfo", "r");
+ if (!f) err("open /proc/meminfo");
+ char *line = NULL;
+ size_t linelen = 0;
+ unsigned val = 0;
+ while (getline(&line, &linelen, f) > 0) {
+ if (sscanf(line, fmt, &val) == 1) {
+ found = 1;
+ break;
+ }
+ }
+ free(line);
+ fclose(f);
+ if (!found) {
+ printf("cannot read HardwareCorruptedPages in meminfo\n");
+ exitcode = 1;
+ }
+ return val;
+}
+
+unsigned hardware_corrupted(void)
+{
+ return (meminfo("HardwareCorrupted: %u") * 1024) / PS;
+}
+
+char *ndesc(char *buf, char *a, char *b)
+{
+ snprintf(buf, 100, "%s %s", a, b);
+ return buf;
+}
+
+void offline(char *name, void *p)
+{
+ char buf[100];
+ if (madvise(p, PS, MADV_SOFT_OFFLINE) < 0)
+ err(ndesc(buf, name, "offline"));
+ corrupted++;
+}
+
+void disk_backed(char *name, int flags)
+{
+ char fn[100];
+ snprintf(fn, sizeof fn, "t%u", getpid());
+ printf("shared, diskbacked\n");
+ int fd = open(fn, O_RDWR|O_CREAT|O_TRUNC, 0644);
+ if (fd < 0) err("open tmpfile");
+ write(fd, empty, sizeof empty);
+ char *p = checked_mmap(NULL, PS, PROT_READ|PROT_WRITE,
+ MAP_SHARED|flags, fd, 0);
+ *(volatile int *)p = 1;
+ offline(ndesc(fn, "disk backed", name), p);
+ munmap(p, PS);
+}
+
+void anonymous(char *name, int flags)
+{
+ char buf[100];
+ char *p = checked_mmap(NULL, PS, PROT_READ|PROT_WRITE,
+ MAP_PRIVATE|MAP_ANONYMOUS|flags, 0, 0);
+ printf("anonymous\n");
+ *(volatile int *)p = 1;
+ offline(ndesc(buf, "anonymous", name), p);
+ *(volatile int *)p = 1;
+ munmap(p, PS);
+}
+
+void check(unsigned *count, char *name)
+{
+ unsigned count2 = hardware_corrupted();
+ unsigned diff = count2 - *count;
+ if (diff != corrupted) {
+ printf("%s: expected %d corrupted pages, got %u\n", name,
+ corrupted,
+ diff);
+ if (diff < corrupted)
+ exitcode = 1;
+ }
+ *count = count2;
+ corrupted = 0;
+}
+
+int main(void)
+{
+ PS = getpagesize();
+
+ unsigned count = hardware_corrupted();
+
+ anonymous("anonymous", 0);
+ check(&count, "anonymous");
+ anonymous("anonymous mlock", MAP_LOCKED);
+ check(&count, "anonymous mlock");
+ disk_backed("disk backed", 0);
+ check(&count, "disk backed");
+ disk_backed("disk backed mlock", 0);
+ check(&count, "disk backed mlock");
+ // add more test cases here
+
+ return exitcode;
+}