qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

mvc.c (2768B)


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