15d69cbdfSDavid Hildenbrand #include <stdint.h> 25d69cbdfSDavid Hildenbrand #include <stdlib.h> 35d69cbdfSDavid Hildenbrand #include <stdio.h> 45d69cbdfSDavid Hildenbrand #include <string.h> 55d69cbdfSDavid Hildenbrand #include <sys/mman.h> 65d69cbdfSDavid Hildenbrand #include <signal.h> 75d69cbdfSDavid Hildenbrand #include <setjmp.h> 85d69cbdfSDavid Hildenbrand 95d69cbdfSDavid Hildenbrand jmp_buf jmp_env; 105d69cbdfSDavid Hildenbrand 115d69cbdfSDavid Hildenbrand static void handle_sigsegv(int sig) 125d69cbdfSDavid Hildenbrand { 135d69cbdfSDavid Hildenbrand siglongjmp(jmp_env, 1); 145d69cbdfSDavid Hildenbrand } 155d69cbdfSDavid Hildenbrand 165d69cbdfSDavid Hildenbrand #define ALLOC_SIZE (2 * 4096) 175d69cbdfSDavid Hildenbrand 185d69cbdfSDavid Hildenbrand static inline void mvc_256(const char *dst, const char *src) 195d69cbdfSDavid Hildenbrand { 205d69cbdfSDavid Hildenbrand asm volatile ( 215d69cbdfSDavid Hildenbrand " mvc 0(256,%[dst]),0(%[src])\n" 225d69cbdfSDavid Hildenbrand : 23*f530ba8fSThomas Huth : [dst] "a" (dst), 24*f530ba8fSThomas Huth [src] "a" (src) 255d69cbdfSDavid Hildenbrand : "memory"); 265d69cbdfSDavid Hildenbrand } 275d69cbdfSDavid Hildenbrand 285d69cbdfSDavid Hildenbrand int main(void) 295d69cbdfSDavid Hildenbrand { 305d69cbdfSDavid Hildenbrand char *src, *dst; 315d69cbdfSDavid Hildenbrand int i; 325d69cbdfSDavid Hildenbrand 335d69cbdfSDavid Hildenbrand /* register the SIGSEGV handler */ 345d69cbdfSDavid Hildenbrand if (signal(SIGSEGV, handle_sigsegv) == SIG_ERR) { 355d69cbdfSDavid Hildenbrand fprintf(stderr, "SIGSEGV not registered\n"); 365d69cbdfSDavid Hildenbrand return 1; 375d69cbdfSDavid Hildenbrand } 385d69cbdfSDavid Hildenbrand 395d69cbdfSDavid Hildenbrand /* prepare the buffers - two consecutive pages */ 405d69cbdfSDavid Hildenbrand src = valloc(ALLOC_SIZE); 415d69cbdfSDavid Hildenbrand dst = valloc(ALLOC_SIZE); 425d69cbdfSDavid Hildenbrand memset(src, 0xff, ALLOC_SIZE); 435d69cbdfSDavid Hildenbrand memset(dst, 0x0, ALLOC_SIZE); 445d69cbdfSDavid Hildenbrand 455d69cbdfSDavid Hildenbrand /* protect the second pages */ 465d69cbdfSDavid Hildenbrand if (mprotect(src + 4096, 4096, PROT_NONE) || 475d69cbdfSDavid Hildenbrand mprotect(dst + 4096, 4096, PROT_NONE)) { 485d69cbdfSDavid Hildenbrand fprintf(stderr, "mprotect failed\n"); 495d69cbdfSDavid Hildenbrand return 1; 505d69cbdfSDavid Hildenbrand } 515d69cbdfSDavid Hildenbrand 525d69cbdfSDavid Hildenbrand /* fault on second destination page */ 535d69cbdfSDavid Hildenbrand if (sigsetjmp(jmp_env, 1) == 0) { 545d69cbdfSDavid Hildenbrand mvc_256(dst + 4096 - 128, src); 555d69cbdfSDavid Hildenbrand fprintf(stderr, "fault not triggered\n"); 565d69cbdfSDavid Hildenbrand return 1; 575d69cbdfSDavid Hildenbrand } 585d69cbdfSDavid Hildenbrand 595d69cbdfSDavid Hildenbrand /* fault on second source page */ 605d69cbdfSDavid Hildenbrand if (sigsetjmp(jmp_env, 1) == 0) { 615d69cbdfSDavid Hildenbrand mvc_256(dst, src + 4096 - 128); 625d69cbdfSDavid Hildenbrand fprintf(stderr, "fault not triggered\n"); 635d69cbdfSDavid Hildenbrand return 1; 645d69cbdfSDavid Hildenbrand } 655d69cbdfSDavid Hildenbrand 665d69cbdfSDavid Hildenbrand /* fault on second source and second destination page */ 675d69cbdfSDavid Hildenbrand if (sigsetjmp(jmp_env, 1) == 0) { 685d69cbdfSDavid Hildenbrand mvc_256(dst + 4096 - 128, src + 4096 - 128); 695d69cbdfSDavid Hildenbrand fprintf(stderr, "fault not triggered\n"); 705d69cbdfSDavid Hildenbrand return 1; 715d69cbdfSDavid Hildenbrand } 725d69cbdfSDavid Hildenbrand 735d69cbdfSDavid Hildenbrand /* restore permissions */ 745d69cbdfSDavid Hildenbrand if (mprotect(src + 4096, 4096, PROT_READ | PROT_WRITE) || 755d69cbdfSDavid Hildenbrand mprotect(dst + 4096, 4096, PROT_READ | PROT_WRITE)) { 765d69cbdfSDavid Hildenbrand fprintf(stderr, "mprotect failed\n"); 775d69cbdfSDavid Hildenbrand return 1; 785d69cbdfSDavid Hildenbrand } 795d69cbdfSDavid Hildenbrand 805d69cbdfSDavid Hildenbrand /* no data must be touched during the faults */ 815d69cbdfSDavid Hildenbrand for (i = 0; i < ALLOC_SIZE; i++) { 825d69cbdfSDavid Hildenbrand if (src[i] != 0xff || dst[i]) { 835d69cbdfSDavid Hildenbrand fprintf(stderr, "data modified during a fault\n"); 845d69cbdfSDavid Hildenbrand return 1; 855d69cbdfSDavid Hildenbrand } 865d69cbdfSDavid Hildenbrand } 875d69cbdfSDavid Hildenbrand 885d69cbdfSDavid Hildenbrand /* test if MVC works now correctly accross page boundaries */ 895d69cbdfSDavid Hildenbrand mvc_256(dst + 4096 - 128, src + 4096 - 128); 905d69cbdfSDavid Hildenbrand for (i = 0; i < ALLOC_SIZE; i++) { 915d69cbdfSDavid Hildenbrand if (src[i] != 0xff) { 925d69cbdfSDavid Hildenbrand fprintf(stderr, "src modified\n"); 935d69cbdfSDavid Hildenbrand return 1; 945d69cbdfSDavid Hildenbrand } 955d69cbdfSDavid Hildenbrand if (i < 4096 - 128 || i >= 4096 + 128) { 965d69cbdfSDavid Hildenbrand if (dst[i]) { 975d69cbdfSDavid Hildenbrand fprintf(stderr, "wrong dst modified\n"); 985d69cbdfSDavid Hildenbrand return 1; 995d69cbdfSDavid Hildenbrand } 1005d69cbdfSDavid Hildenbrand } else { 1015d69cbdfSDavid Hildenbrand if (dst[i] != 0xff) { 1025d69cbdfSDavid Hildenbrand fprintf(stderr, "wrong data moved\n"); 1035d69cbdfSDavid Hildenbrand return 1; 1045d69cbdfSDavid Hildenbrand } 1055d69cbdfSDavid Hildenbrand } 1065d69cbdfSDavid Hildenbrand } 1075d69cbdfSDavid Hildenbrand 1085d69cbdfSDavid Hildenbrand return 0; 1095d69cbdfSDavid Hildenbrand } 110