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

xbzrle.c (4179B)


      1/*
      2 * Xor Based Zero Run Length Encoding
      3 *
      4 * Copyright 2013 Red Hat, Inc. and/or its affiliates
      5 *
      6 * Authors:
      7 *  Orit Wasserman  <owasserm@redhat.com>
      8 *
      9 * This work is licensed under the terms of the GNU GPL, version 2 or later.
     10 * See the COPYING file in the top-level directory.
     11 *
     12 */
     13#include "qemu/osdep.h"
     14#include "qemu/cutils.h"
     15#include "xbzrle.h"
     16
     17/*
     18  page = zrun nzrun
     19       | zrun nzrun page
     20
     21  zrun = length
     22
     23  nzrun = length byte...
     24
     25  length = uleb128 encoded integer
     26 */
     27int xbzrle_encode_buffer(uint8_t *old_buf, uint8_t *new_buf, int slen,
     28                         uint8_t *dst, int dlen)
     29{
     30    uint32_t zrun_len = 0, nzrun_len = 0;
     31    int d = 0, i = 0;
     32    long res;
     33    uint8_t *nzrun_start = NULL;
     34
     35    g_assert(!(((uintptr_t)old_buf | (uintptr_t)new_buf | slen) %
     36               sizeof(long)));
     37
     38    while (i < slen) {
     39        /* overflow */
     40        if (d + 2 > dlen) {
     41            return -1;
     42        }
     43
     44        /* not aligned to sizeof(long) */
     45        res = (slen - i) % sizeof(long);
     46        while (res && old_buf[i] == new_buf[i]) {
     47            zrun_len++;
     48            i++;
     49            res--;
     50        }
     51
     52        /* word at a time for speed */
     53        if (!res) {
     54            while (i < slen &&
     55                   (*(long *)(old_buf + i)) == (*(long *)(new_buf + i))) {
     56                i += sizeof(long);
     57                zrun_len += sizeof(long);
     58            }
     59
     60            /* go over the rest */
     61            while (i < slen && old_buf[i] == new_buf[i]) {
     62                zrun_len++;
     63                i++;
     64            }
     65        }
     66
     67        /* buffer unchanged */
     68        if (zrun_len == slen) {
     69            return 0;
     70        }
     71
     72        /* skip last zero run */
     73        if (i == slen) {
     74            return d;
     75        }
     76
     77        d += uleb128_encode_small(dst + d, zrun_len);
     78
     79        zrun_len = 0;
     80        nzrun_start = new_buf + i;
     81
     82        /* overflow */
     83        if (d + 2 > dlen) {
     84            return -1;
     85        }
     86        /* not aligned to sizeof(long) */
     87        res = (slen - i) % sizeof(long);
     88        while (res && old_buf[i] != new_buf[i]) {
     89            i++;
     90            nzrun_len++;
     91            res--;
     92        }
     93
     94        /* word at a time for speed, use of 32-bit long okay */
     95        if (!res) {
     96            /* truncation to 32-bit long okay */
     97            unsigned long mask = (unsigned long)0x0101010101010101ULL;
     98            while (i < slen) {
     99                unsigned long xor;
    100                xor = *(unsigned long *)(old_buf + i)
    101                    ^ *(unsigned long *)(new_buf + i);
    102                if ((xor - mask) & ~xor & (mask << 7)) {
    103                    /* found the end of an nzrun within the current long */
    104                    while (old_buf[i] != new_buf[i]) {
    105                        nzrun_len++;
    106                        i++;
    107                    }
    108                    break;
    109                } else {
    110                    i += sizeof(long);
    111                    nzrun_len += sizeof(long);
    112                }
    113            }
    114        }
    115
    116        d += uleb128_encode_small(dst + d, nzrun_len);
    117        /* overflow */
    118        if (d + nzrun_len > dlen) {
    119            return -1;
    120        }
    121        memcpy(dst + d, nzrun_start, nzrun_len);
    122        d += nzrun_len;
    123        nzrun_len = 0;
    124    }
    125
    126    return d;
    127}
    128
    129int xbzrle_decode_buffer(uint8_t *src, int slen, uint8_t *dst, int dlen)
    130{
    131    int i = 0, d = 0;
    132    int ret;
    133    uint32_t count = 0;
    134
    135    while (i < slen) {
    136
    137        /* zrun */
    138        if ((slen - i) < 2) {
    139            return -1;
    140        }
    141
    142        ret = uleb128_decode_small(src + i, &count);
    143        if (ret < 0 || (i && !count)) {
    144            return -1;
    145        }
    146        i += ret;
    147        d += count;
    148
    149        /* overflow */
    150        if (d > dlen) {
    151            return -1;
    152        }
    153
    154        /* nzrun */
    155        if ((slen - i) < 2) {
    156            return -1;
    157        }
    158
    159        ret = uleb128_decode_small(src + i, &count);
    160        if (ret < 0 || !count) {
    161            return -1;
    162        }
    163        i += ret;
    164
    165        /* overflow */
    166        if (d + count > dlen || i + count > slen) {
    167            return -1;
    168        }
    169
    170        memcpy(dst + d, src + i, count);
    171        d += count;
    172        i += count;
    173    }
    174
    175    return d;
    176}