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