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