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
handle_sigsegv(int sig)11 static void handle_sigsegv(int sig)
12 {
13 siglongjmp(jmp_env, 1);
14 }
15
16 #define ALLOC_SIZE (2 * 4096)
17
mvc_256(const char * dst,const char * src)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
main(void)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