1*5d69cbdfSDavid Hildenbrand #include <stdint.h> 2*5d69cbdfSDavid Hildenbrand #include <stdlib.h> 3*5d69cbdfSDavid Hildenbrand #include <stdio.h> 4*5d69cbdfSDavid Hildenbrand #include <string.h> 5*5d69cbdfSDavid Hildenbrand #include <sys/mman.h> 6*5d69cbdfSDavid Hildenbrand #include <signal.h> 7*5d69cbdfSDavid Hildenbrand #include <setjmp.h> 8*5d69cbdfSDavid Hildenbrand 9*5d69cbdfSDavid Hildenbrand jmp_buf jmp_env; 10*5d69cbdfSDavid Hildenbrand 11*5d69cbdfSDavid Hildenbrand static void handle_sigsegv(int sig) 12*5d69cbdfSDavid Hildenbrand { 13*5d69cbdfSDavid Hildenbrand siglongjmp(jmp_env, 1); 14*5d69cbdfSDavid Hildenbrand } 15*5d69cbdfSDavid Hildenbrand 16*5d69cbdfSDavid Hildenbrand #define ALLOC_SIZE (2 * 4096) 17*5d69cbdfSDavid Hildenbrand 18*5d69cbdfSDavid Hildenbrand static inline void mvc_256(const char *dst, const char *src) 19*5d69cbdfSDavid Hildenbrand { 20*5d69cbdfSDavid Hildenbrand asm volatile ( 21*5d69cbdfSDavid Hildenbrand " mvc 0(256,%[dst]),0(%[src])\n" 22*5d69cbdfSDavid Hildenbrand : 23*5d69cbdfSDavid Hildenbrand : [dst] "d" (dst), 24*5d69cbdfSDavid Hildenbrand [src] "d" (src) 25*5d69cbdfSDavid Hildenbrand : "memory"); 26*5d69cbdfSDavid Hildenbrand } 27*5d69cbdfSDavid Hildenbrand 28*5d69cbdfSDavid Hildenbrand int main(void) 29*5d69cbdfSDavid Hildenbrand { 30*5d69cbdfSDavid Hildenbrand char *src, *dst; 31*5d69cbdfSDavid Hildenbrand int i; 32*5d69cbdfSDavid Hildenbrand 33*5d69cbdfSDavid Hildenbrand /* register the SIGSEGV handler */ 34*5d69cbdfSDavid Hildenbrand if (signal(SIGSEGV, handle_sigsegv) == SIG_ERR) { 35*5d69cbdfSDavid Hildenbrand fprintf(stderr, "SIGSEGV not registered\n"); 36*5d69cbdfSDavid Hildenbrand return 1; 37*5d69cbdfSDavid Hildenbrand } 38*5d69cbdfSDavid Hildenbrand 39*5d69cbdfSDavid Hildenbrand /* prepare the buffers - two consecutive pages */ 40*5d69cbdfSDavid Hildenbrand src = valloc(ALLOC_SIZE); 41*5d69cbdfSDavid Hildenbrand dst = valloc(ALLOC_SIZE); 42*5d69cbdfSDavid Hildenbrand memset(src, 0xff, ALLOC_SIZE); 43*5d69cbdfSDavid Hildenbrand memset(dst, 0x0, ALLOC_SIZE); 44*5d69cbdfSDavid Hildenbrand 45*5d69cbdfSDavid Hildenbrand /* protect the second pages */ 46*5d69cbdfSDavid Hildenbrand if (mprotect(src + 4096, 4096, PROT_NONE) || 47*5d69cbdfSDavid Hildenbrand mprotect(dst + 4096, 4096, PROT_NONE)) { 48*5d69cbdfSDavid Hildenbrand fprintf(stderr, "mprotect failed\n"); 49*5d69cbdfSDavid Hildenbrand return 1; 50*5d69cbdfSDavid Hildenbrand } 51*5d69cbdfSDavid Hildenbrand 52*5d69cbdfSDavid Hildenbrand /* fault on second destination page */ 53*5d69cbdfSDavid Hildenbrand if (sigsetjmp(jmp_env, 1) == 0) { 54*5d69cbdfSDavid Hildenbrand mvc_256(dst + 4096 - 128, src); 55*5d69cbdfSDavid Hildenbrand fprintf(stderr, "fault not triggered\n"); 56*5d69cbdfSDavid Hildenbrand return 1; 57*5d69cbdfSDavid Hildenbrand } 58*5d69cbdfSDavid Hildenbrand 59*5d69cbdfSDavid Hildenbrand /* fault on second source page */ 60*5d69cbdfSDavid Hildenbrand if (sigsetjmp(jmp_env, 1) == 0) { 61*5d69cbdfSDavid Hildenbrand mvc_256(dst, src + 4096 - 128); 62*5d69cbdfSDavid Hildenbrand fprintf(stderr, "fault not triggered\n"); 63*5d69cbdfSDavid Hildenbrand return 1; 64*5d69cbdfSDavid Hildenbrand } 65*5d69cbdfSDavid Hildenbrand 66*5d69cbdfSDavid Hildenbrand /* fault on second source and second destination page */ 67*5d69cbdfSDavid Hildenbrand if (sigsetjmp(jmp_env, 1) == 0) { 68*5d69cbdfSDavid Hildenbrand mvc_256(dst + 4096 - 128, src + 4096 - 128); 69*5d69cbdfSDavid Hildenbrand fprintf(stderr, "fault not triggered\n"); 70*5d69cbdfSDavid Hildenbrand return 1; 71*5d69cbdfSDavid Hildenbrand } 72*5d69cbdfSDavid Hildenbrand 73*5d69cbdfSDavid Hildenbrand /* restore permissions */ 74*5d69cbdfSDavid Hildenbrand if (mprotect(src + 4096, 4096, PROT_READ | PROT_WRITE) || 75*5d69cbdfSDavid Hildenbrand mprotect(dst + 4096, 4096, PROT_READ | PROT_WRITE)) { 76*5d69cbdfSDavid Hildenbrand fprintf(stderr, "mprotect failed\n"); 77*5d69cbdfSDavid Hildenbrand return 1; 78*5d69cbdfSDavid Hildenbrand } 79*5d69cbdfSDavid Hildenbrand 80*5d69cbdfSDavid Hildenbrand /* no data must be touched during the faults */ 81*5d69cbdfSDavid Hildenbrand for (i = 0; i < ALLOC_SIZE; i++) { 82*5d69cbdfSDavid Hildenbrand if (src[i] != 0xff || dst[i]) { 83*5d69cbdfSDavid Hildenbrand fprintf(stderr, "data modified during a fault\n"); 84*5d69cbdfSDavid Hildenbrand return 1; 85*5d69cbdfSDavid Hildenbrand } 86*5d69cbdfSDavid Hildenbrand } 87*5d69cbdfSDavid Hildenbrand 88*5d69cbdfSDavid Hildenbrand /* test if MVC works now correctly accross page boundaries */ 89*5d69cbdfSDavid Hildenbrand mvc_256(dst + 4096 - 128, src + 4096 - 128); 90*5d69cbdfSDavid Hildenbrand for (i = 0; i < ALLOC_SIZE; i++) { 91*5d69cbdfSDavid Hildenbrand if (src[i] != 0xff) { 92*5d69cbdfSDavid Hildenbrand fprintf(stderr, "src modified\n"); 93*5d69cbdfSDavid Hildenbrand return 1; 94*5d69cbdfSDavid Hildenbrand } 95*5d69cbdfSDavid Hildenbrand if (i < 4096 - 128 || i >= 4096 + 128) { 96*5d69cbdfSDavid Hildenbrand if (dst[i]) { 97*5d69cbdfSDavid Hildenbrand fprintf(stderr, "wrong dst modified\n"); 98*5d69cbdfSDavid Hildenbrand return 1; 99*5d69cbdfSDavid Hildenbrand } 100*5d69cbdfSDavid Hildenbrand } else { 101*5d69cbdfSDavid Hildenbrand if (dst[i] != 0xff) { 102*5d69cbdfSDavid Hildenbrand fprintf(stderr, "wrong data moved\n"); 103*5d69cbdfSDavid Hildenbrand return 1; 104*5d69cbdfSDavid Hildenbrand } 105*5d69cbdfSDavid Hildenbrand } 106*5d69cbdfSDavid Hildenbrand } 107*5d69cbdfSDavid Hildenbrand 108*5d69cbdfSDavid Hildenbrand return 0; 109*5d69cbdfSDavid Hildenbrand } 110