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
handle_sigsegv(int sig)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
mvc_256(const char * dst,const char * src)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 :
23f530ba8fSThomas Huth : [dst] "a" (dst),
24f530ba8fSThomas Huth [src] "a" (src)
255d69cbdfSDavid Hildenbrand : "memory");
265d69cbdfSDavid Hildenbrand }
275d69cbdfSDavid Hildenbrand
main(void)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
88*cced0d65SMichael Tokarev /* test if MVC works now correctly across 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