aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndi Kleen <ak@linux.intel.com>2010-11-08 11:41:32 +0100
committerAndi Kleen <ak@linux.intel.com>2010-11-08 11:41:32 +0100
commit717a2621b5103b90f2028137c2964f7a3acac8ba (patch)
tree429007fbead94ee58bffbac8dc5d7fab5164e81f
parentdcfa4b811cdcb12ad26089d090cce88a31d29a4e (diff)
parent1b6726dadea10127264d840ca213d4340b072a7c (diff)
downloadmce-test-717a2621b5103b90f2028137c2964f7a3acac8ba.tar.gz
Merge branch 'master' of git://git.kernel.org/pub/scm/utils/cpu/mce/mce-test
-rw-r--r--tsrc/hugepage.h181
-rw-r--r--tsrc/thugetlb.c136
-rw-r--r--tsrc/tinjpage.c203
-rw-r--r--tsrc/tsoftinj.c72
-rw-r--r--tsrc/utils.h1
5 files changed, 471 insertions, 122 deletions
diff --git a/tsrc/hugepage.h b/tsrc/hugepage.h
new file mode 100644
index 0000000..d44e5ac
--- /dev/null
+++ b/tsrc/hugepage.h
@@ -0,0 +1,181 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <sys/mman.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+
+int HPS;
+char hugetlbfsdir[256];
+#ifndef UTILS
+#include "utils.h"
+#endif
+#define errmsg(x) fprintf(stderr, x), exit(1)
+
+void write_hugepage(char *addr, int size, char *avoid)
+{
+ int i, j;
+ for (i = 0; i < size; i++) {
+ if (addr == avoid)
+ continue;
+ for (j = 0; j < HPS; j++) {
+ *(addr + i * HPS + j) = (char)('a' + ((i + j) % 26));
+ }
+ }
+}
+
+/* return -1 if buffer content differs from the expected ones */
+int read_hugepage(char *addr, int size, char *avoid)
+{
+ int i, j;
+ int ret = 0;
+
+ for (i = 0; i < size; i++) {
+ if (addr == avoid)
+ continue;
+ for (j = 0; j < HPS; j++) {
+ if (*(addr + i * HPS + j) != (char)('a' + ((i + j) % 26))) {
+ printf("Mismatch at %d\n", i + j);
+ ret = -1;
+ break;
+ }
+ }
+ }
+ return ret;
+}
+
+int hugetlbfs_root(char *dir)
+{
+ int found = 0;
+ FILE *f = fopen("/proc/mounts", "r");
+ if (!f) err("open /proc/mounts");
+ char *line = NULL;
+ size_t linelen = 0;
+ char dummy[100];
+ while (getline(&line, &linelen, f) > 0) {
+ if (sscanf(line, "none %s hugetlbfs %[^ ]",
+ dir, dummy) >= 2) {
+ found = 1;
+ break;
+ }
+ }
+ free(line);
+ fclose(f);
+ if (!found)
+ printf("cannot find hugetlbfs directory in /proc/mounts\n");
+ return found;
+}
+
+/* Assume there is only one types of hugepage size for now. */
+int gethugepagesize(void)
+{
+ int hpagesize = 0;
+ struct dirent *dent;
+ DIR *dir;
+ dir = opendir("/sys/kernel/mm/hugepages");
+ if (!dir) err("open /sys/kernel/mm/hugepages");
+ while ((dent = readdir(dir)) != NULL)
+ if (sscanf(dent->d_name, "hugepages-%dkB", &hpagesize) >= 1)
+ break;
+ closedir(dir);
+ return hpagesize * 1024;
+}
+
+void *alloc_shm_hugepage(int *key, int size)
+{
+ void *addr;
+ int shmid;
+ if ((shmid = shmget(*key, size,
+ SHM_HUGETLB | IPC_CREAT | SHM_R | SHM_W)) < 0) {
+ perror("shmget");
+ return NULL;
+ }
+ addr = shmat(shmid, (void *)0x0UL, 0);
+ if (addr == (char *)-1) {
+ perror("Shared memory attach failure");
+ shmctl(shmid, IPC_RMID, NULL);
+ return NULL;
+ }
+ *key = shmid;
+ return addr;
+}
+
+void *alloc_anonymous_hugepage(int size, int private)
+{
+ void *addr;
+ int mapflag = MAP_ANONYMOUS | 0x40000; /* MAP_HUGETLB */
+ if (private)
+ mapflag |= MAP_PRIVATE;
+ else
+ mapflag |= MAP_SHARED;
+ if ((addr = mmap(0, size,
+ PROT_READ|PROT_WRITE, mapflag, -1, 0)) == MAP_FAILED) {
+ perror("mmap");
+ return NULL;
+ }
+ return addr;
+}
+
+void *alloc_filebacked_hugepage(char *filepath, int size, int private, int *fd)
+{
+ int mapflag = MAP_SHARED;
+ void *addr;
+ if (private)
+ mapflag = MAP_PRIVATE;
+ if ((*fd = open(filepath, O_CREAT | O_RDWR, 0777)) < 0) {
+ perror("open");
+ return NULL;
+ }
+ if ((addr = mmap(0, size,
+ PROT_READ|PROT_WRITE, mapflag, *fd, 0)) == MAP_FAILED) {
+ perror("mmap");
+ unlink(filepath);
+ return NULL;
+ }
+ return addr;
+}
+
+int free_shm_hugepage(int key, void *addr)
+{
+ if (shmdt((const void *)addr) != 0) {
+ perror("Detach failure");
+ shmctl(key, IPC_RMID, NULL);
+ return -1;
+ }
+ shmctl(key, IPC_RMID, NULL);
+ return 0;
+}
+
+int free_anonymous_hugepage(void *addr, int size)
+{
+ int ret = 0;
+ if (munmap(addr, size)) {
+ perror("munmap");
+ ret = -1;
+ }
+ return ret;
+}
+
+int free_filebacked_hugepage(void *addr, int size, int fd, char *filepath)
+{
+ int ret = 0;
+ if (munmap(addr, size)) {
+ perror("munmap");
+ ret = -1;
+ }
+ if (close(fd)) {
+ perror("close");
+ ret = -1;
+ }
+ if (filepath) {
+ if (unlink(filepath)) {
+ perror("unlink");
+ ret = -1;
+ }
+ } else {
+ fprintf(stderr, "Filepath not specified.\n");
+ ret = -1;
+ }
+ return ret;
+}
diff --git a/tsrc/thugetlb.c b/tsrc/thugetlb.c
index b941e7e..28a1f10 100644
--- a/tsrc/thugetlb.c
+++ b/tsrc/thugetlb.c
@@ -2,6 +2,7 @@
* Test program for memory error handling for hugepages
* Author: Naoya Horiguchi <n-horiguchi@ah.jp.nec.com>
*/
+#define _GNU_SOURCE 1
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@@ -16,6 +17,7 @@
#include <sys/types.h>
#include <sys/prctl.h>
#include <sys/wait.h>
+#include "hugepage.h"
#define FILE_BASE "test"
@@ -36,6 +38,9 @@
#define PR_MCE_KILL_DEFAULT 2
#define PR_MCE_KILL_GET 34
+#define MADV_HWPOISON 100
+#define MADV_SOFT_OFFLINE 101
+
int PS; /* Page size */
int file_size; /* Memory allocation size (hugepage unit) */
/* Error injection position (page offset from the first hugepage head) */
@@ -45,16 +50,14 @@ char filepath[BUF_SIZE];
#define DEB printf("DEBUG [%d:%s:%d]\n", getpid(), __FILE__, __LINE__);
-#define err(x) perror(x), exit(1)
-#define errmsg(x) fprintf(stderr, x), exit(1)
-
static void usage(void)
{
printf(
-"./thugetlb [-m memory] [-o offset] [-f file] [-xeSAaFpch] hugetlbfs_directory\n"
+"./thugetlb [-m memory] [-o offset] [-f file] [-xOeSAaFpch] hugetlbfs_directory\n"
" -m|--memory size(hugepage unit) Size of hugetlbfs file\n"
" -o|--offset offset(page unit) Position of error injection\n"
" -x|--inject Error injection switch\n"
+" -O|--offline Soft offline switch\n"
" -e|--early-kill Set PR_MCE_KILL_EARLY\n"
" -S|--shm Use shmem with SHM_HUGETLB\n"
" -A|--anonymous Use MAP_ANONYMOUS\n"
@@ -87,45 +90,11 @@ int put_semaphore(int sem_id, struct sembuf *sembuffer)
return semop(sem_id, sembuffer, 1);
}
-static int avoid_hpage(void *addr, int flag, char *avoid)
-{
- return flag == 1 && addr == avoid;
-}
-
-static void write_bytes(char *addr, int flag, char *avoid)
-{
- int i, j;
- for (i = 0; i < file_size; i++) {
- if (avoid_hpage(addr + i * HPAGE_SIZE, flag, avoid))
- continue;
- for (j = 0; j < HPAGE_SIZE; j++) {
- *(addr + i * HPAGE_SIZE + j) = (char)('a' +
- ((i + j) % 26));
- }
- }
-}
-
-static void read_bytes(char *addr, int flag, char *avoid)
-{
- int i, j;
-
- for (i = 0; i < file_size; i++) {
- if (avoid_hpage(addr + i * HPAGE_SIZE, flag, avoid))
- continue;
- for (j = 0; j < HPAGE_SIZE; j++) {
- if (*(addr + i * HPAGE_SIZE + j) != (char)('a' +
- ((i + j) % 26))) {
- printf("Mismatch at %u\n", i + j);
- break;
- }
- }
- }
-}
-
static struct option opts[] = {
{ "memory" , 1, NULL, 'm' },
{ "offset" , 1, NULL, 'o' },
{ "inject" , 0, NULL, 'x' },
+ { "offline" , 0, NULL, 'O' },
{ "early_kill" , 0, NULL, 'e' },
{ "shm" , 0, NULL, 'S' },
{ "anonymous" , 0, NULL, 'A' },
@@ -144,10 +113,10 @@ int main(int argc, char *argv[])
int i;
int ret;
int fd = 0;
- int shmid;
int semid;
int semaphore;
int inject = 0;
+ int madvise_code = MADV_HWPOISON;
int early_kill = 0;
int avoid_touch = 0;
int anonflag = 0;
@@ -162,6 +131,7 @@ int main(int argc, char *argv[])
struct sembuf sembuffer;
PS = getpagesize();
+ HPS = HPAGE_SIZE;
file_size = 1;
corrupt_page = -1;
@@ -171,7 +141,7 @@ int main(int argc, char *argv[])
}
while ((c = getopt_long(argc, argv,
- "m:o:xeSAaFpcf:h", opts, NULL)) != -1) {
+ "m:o:xOeSAaFpcf:h", opts, NULL)) != -1) {
switch (c) {
case 'm':
file_size = strtol(optarg, NULL, 10);
@@ -182,6 +152,9 @@ int main(int argc, char *argv[])
case 'x':
inject = 1;
break;
+ case 'O':
+ madvise_code = MADV_SOFT_OFFLINE;
+ break;
case 'e':
early_kill = 1;
break;
@@ -232,38 +205,23 @@ int main(int argc, char *argv[])
}
if (shmflag) {
- if ((shmid = shmget(shmkey, file_size * HPAGE_SIZE,
- SHM_HUGETLB | IPC_CREAT | SHM_R | SHM_W)) < 0)
- err("shmget");
- addr = shmat(shmid, (void *)0x0UL, 0);
- if (addr == (char *)-1) {
- perror("Shared memory attach failure");
- shmctl(shmid, IPC_RMID, NULL);
- exit(2);
- }
+ addr = alloc_shm_hugepage(&shmkey, file_size * HPAGE_SIZE);
+ if (!addr)
+ errmsg("Failed in alloc_shm_hugepage()");
} else if (anonflag) {
- int mapflag = MAP_ANONYMOUS | 0x40000; /* MAP_HUGETLB */
- if (privateflag)
- mapflag |= MAP_PRIVATE;
- else
- mapflag |= MAP_SHARED;
- if ((addr = mmap(0, file_size * HPAGE_SIZE,
- PROTECTION, mapflag, -1, 0)) == MAP_FAILED)
- err("mmap");
+ addr = alloc_anonymous_hugepage(file_size * HPAGE_SIZE,
+ privateflag);
+ if (!addr)
+ errmsg("Failed in alloc_anonymous_hugepage()");
} else {
- int mapflag = MAP_SHARED;
- if (privateflag)
- mapflag = MAP_PRIVATE;
- if ((fd = open(filepath, O_CREAT | O_RDWR, 0777)) < 0)
- err("Open failed");
- if ((addr = mmap(0, file_size * HPAGE_SIZE,
- PROTECTION, mapflag, fd, 0)) == MAP_FAILED) {
- unlink(filepath);
- err("mmap");
- }
+ addr = alloc_filebacked_hugepage(filepath,
+ file_size * HPAGE_SIZE,
+ privateflag, &fd);
+ if (!addr)
+ errmsg("Failed in alloc_filebacked_hugepage()");
}
- if (corrupt_page != -1)
+ if (corrupt_page != -1 && avoid_touch)
expected_addr = (void *)(addr + corrupt_page / 512 * HPAGE_SIZE);
if (forkflag) {
@@ -283,8 +241,8 @@ int main(int argc, char *argv[])
}
}
- write_bytes(addr, 0, 0);
- read_bytes(addr, 0, 0);
+ write_hugepage(addr, file_size, 0);
+ read_hugepage(addr, file_size, 0);
if (early_kill)
prctl(PR_MCE_KILL, PR_MCE_KILL_SET, PR_MCE_KILL_EARLY,
@@ -301,8 +259,8 @@ int main(int argc, char *argv[])
if (!pid) {
/* Semaphore is already held */
if (cowflag) {
- write_bytes(addr, 0, expected_addr);
- read_bytes(addr, 0, expected_addr);
+ write_hugepage(addr, 0, expected_addr);
+ read_hugepage(addr, 0, expected_addr);
}
if (put_semaphore(semid, &sembuffer))
err("put_semaphore");
@@ -323,7 +281,7 @@ int main(int argc, char *argv[])
}
if (inject && corrupt_page != -1) {
- ret = madvise(addr + corrupt_page * PS, PS, 100);
+ ret = madvise(addr + corrupt_page * PS, PS, madvise_code);
if (ret) {
printf("madivise return %d :", ret);
perror("madvise");
@@ -336,27 +294,27 @@ int main(int argc, char *argv[])
goto cleanout;
}
- write_bytes(addr, avoid_touch, expected_addr);
- read_bytes(addr, avoid_touch, expected_addr);
+ if (madvise_code != MADV_SOFT_OFFLINE);
+ write_hugepage(addr, file_size, expected_addr);
+ read_hugepage(addr, file_size, expected_addr);
- if (forkflag)
+ if (forkflag) {
if (wait(&i) == -1)
err("wait");
+ if (semctl(semid, 0, IPC_RMID) == -1)
+ err("semctl(IPC_RMID)");
+ }
cleanout:
if (shmflag) {
- if (shmdt((const void *)addr) != 0) {
- err("Detach failure");
- shmctl(shmid, IPC_RMID, NULL);
- exit(EXIT_FAILURE);
- }
- shmctl(shmid, IPC_RMID, NULL);
+ if (free_shm_hugepage(shmkey, addr) == -1)
+ exit(2);
+ } else if (anonflag) {
+ if (free_anonymous_hugepage(addr, file_size * HPAGE_SIZE) == -1)
+ exit(2);
} else {
- if (munmap(addr, file_size * HPAGE_SIZE))
- err("munmap");
- if (close(fd))
- err("close");
- if (!anonflag && unlink(filepath))
- err("unlink");
+ if (free_filebacked_hugepage(addr, file_size * HPAGE_SIZE,
+ fd, filepath) == -1)
+ exit(2);
}
return 0;
diff --git a/tsrc/tinjpage.c b/tsrc/tinjpage.c
index fd98a4f..bee38af 100644
--- a/tsrc/tinjpage.c
+++ b/tsrc/tinjpage.c
@@ -3,7 +3,7 @@
* This injects poison into various mapping cases and triggers the poison
* handling. Requires special injection support in the kernel.
*
- * Copyright 2009 Intel Corporation
+ * 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
@@ -37,13 +37,14 @@
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
+#include "utils.h"
+#include "hugepage.h"
#define MADV_POISON 100
#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")
@@ -53,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)
@@ -83,11 +87,40 @@ void *xmalloc(size_t s)
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) {
@@ -96,6 +129,17 @@ void sighandler(int sig, siginfo_t *si, void *arg)
failure++;
}
+ 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) {
@@ -117,22 +161,79 @@ enum rmode {
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++;
@@ -687,6 +788,55 @@ 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);
char *name;
@@ -703,6 +853,9 @@ struct testcase {
{ nonlinear, "nonlinear" },
{ 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 */
{}
@@ -717,20 +870,26 @@ void usage(void)
{
fprintf(stderr, "Usage: tinjpage [--sniper]\n"
"Test hwpoison injection on pages in various states\n"
- "--sniper: Enable racy sniper tests (likely broken)\n");
+ "--mce-inject Use mce-inject for injection\n"
+ "--sniper Enable racy sniper tests (likely broken)\n");
exit(1);
}
void handle_opts(char **av)
{
- if (!strcmp(av[1], "--sniper")) {
- struct testcase *t;
- for (t = cases; t->f; t++)
- ;
- *t++ = snipercases[0];
- *t++ = snipercases[1];
- } else
- usage();
+ 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)
@@ -739,6 +898,8 @@ int main(int ac, char **av)
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;
diff --git a/tsrc/tsoftinj.c b/tsrc/tsoftinj.c
index 02b0785..c2dfc6c 100644
--- a/tsrc/tsoftinj.c
+++ b/tsrc/tsoftinj.c
@@ -27,10 +27,10 @@
#include <sys/fcntl.h>
#include <stdlib.h>
#include <errno.h>
+#include "hugepage.h"
#define MADV_SOFT_OFFLINE 101
-#define err(x) perror(x), exit(1)
#define TMPDIR "./"
int PS;
@@ -116,15 +116,55 @@ void anonymous(char *name, int flags)
munmap(p, PS);
}
-void check(unsigned *count, char *name)
+void shm_hugepage(char *name, int flags)
+{
+ int shmid = 0;
+ char buf[100];
+ char *p = alloc_shm_hugepage(&shmid, HPS);
+ if (!p)
+ errmsg("failed in alloc_shm_hugepage\n");
+ printf("shm hugepage\n");
+ *(volatile int *)p = 1;
+ offline(ndesc(buf, "shm hugepage", name), p);
+ *(volatile int *)p = 1;
+ free_shm_hugepage(shmid, p);
+}
+
+void anonymous_hugepage(char *name, int flags)
+{
+ char buf[100];
+ char *p = alloc_anonymous_hugepage(HPS, 1);
+ printf("anonymous hugepage\n");
+ *(volatile int *)p = 1;
+ offline(ndesc(buf, "anonymous hugepage", name), p);
+ *(volatile int *)p = 1;
+ free_anonymous_hugepage(p, HPS);
+}
+
+void filebacked_hugepage(char *name, int flags)
+{
+ int fd;
+ char path[100];
+ char fn[100];
+ snprintf(path, sizeof path, "%s/~test-hugepage%u",
+ hugetlbfsdir, getpid());
+ char *p = alloc_filebacked_hugepage(path, HPS, 0, &fd);
+ printf("file backed hugepage\n");
+ *(volatile int *)p = 1;
+ offline(ndesc(fn, "file backed hugepage", name), p);
+ *(volatile int *)p = 1;
+ free_filebacked_hugepage(p, HPS, fd, path);
+}
+
+void check(unsigned *count, char *name, unsigned expected)
{
unsigned count2 = hardware_corrupted();
unsigned diff = count2 - *count;
- if (diff != corrupted) {
+ if (diff != expected) {
printf("%s: expected %d corrupted pages, got %u\n", name,
- corrupted,
+ expected,
diff);
- if (diff < corrupted)
+ if (diff < expected)
exitcode = 1;
}
*count = count2;
@@ -134,17 +174,25 @@ void check(unsigned *count, char *name)
int main(void)
{
PS = getpagesize();
+ HPS = gethugepagesize();
unsigned count = hardware_corrupted();
-
- anonymous("anonymous", 0);
- check(&count, "anonymous");
- anonymous("anonymous mlock", MAP_LOCKED);
- check(&count, "anonymous mlock");
+ if (!hugetlbfs_root(hugetlbfsdir))
+ err("hugetlbfs_root");
+ anonymous("anonymous", 0);
+ check(&count, "anonymous", 1);
+ anonymous("anonymous mlock", MAP_LOCKED);
+ check(&count, "anonymous mlock", 1);
disk_backed("disk backed", 0);
- check(&count, "disk backed");
+ check(&count, "disk backed", 1);
disk_backed("disk backed mlock", 0);
- check(&count, "disk backed mlock");
+ check(&count, "disk backed mlock", 1);
+ shm_hugepage("shm hugepage", 0);
+ check(&count, "shm hugepage", HPS / PS);
+ anonymous_hugepage("anonymous hugepage", 0);
+ check(&count, "anonymous hugepage", HPS / PS);
+ filebacked_hugepage("file backed hugepage", 0);
+ check(&count, "file backed hugepage", HPS / PS);
// add more test cases here
return exitcode;
diff --git a/tsrc/utils.h b/tsrc/utils.h
new file mode 100644
index 0000000..8c8ab26
--- /dev/null
+++ b/tsrc/utils.h
@@ -0,0 +1 @@
+#define err(x) perror(x), exit(1)