xref: /qemu/tests/tcg/s390x/mvc.c (revision 0b58dc456191042dc3b84aa2b80619b71f8b1e3d)
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