qemu/tests/tcg/s390x/mvc.c
<<
>>
Prefs
   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
   9jmp_buf jmp_env;
  10
  11static void handle_sigsegv(int sig)
  12{
  13    siglongjmp(jmp_env, 1);
  14}
  15
  16#define ALLOC_SIZE (2 * 4096)
  17
  18static 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] "d" (dst),
  24          [src] "d" (src)
  25        : "memory");
  26}
  27
  28int 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}
 110