cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

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
      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}