diff options
author | Andi Kleen <ak@linux.intel.com> | 2010-11-08 11:41:32 +0100 |
---|---|---|
committer | Andi Kleen <ak@linux.intel.com> | 2010-11-08 11:41:32 +0100 |
commit | 717a2621b5103b90f2028137c2964f7a3acac8ba (patch) | |
tree | 429007fbead94ee58bffbac8dc5d7fab5164e81f | |
parent | dcfa4b811cdcb12ad26089d090cce88a31d29a4e (diff) | |
parent | 1b6726dadea10127264d840ca213d4340b072a7c (diff) | |
download | mce-test-717a2621b5103b90f2028137c2964f7a3acac8ba.tar.gz |
Merge branch 'master' of git://git.kernel.org/pub/scm/utils/cpu/mce/mce-test
-rw-r--r-- | tsrc/hugepage.h | 181 | ||||
-rw-r--r-- | tsrc/thugetlb.c | 136 | ||||
-rw-r--r-- | tsrc/tinjpage.c | 203 | ||||
-rw-r--r-- | tsrc/tsoftinj.c | 72 | ||||
-rw-r--r-- | tsrc/utils.h | 1 |
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) |