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

vec_helper.c (10089B)


      1/*
      2 * QEMU TCG support -- s390x vector support instructions
      3 *
      4 * Copyright (C) 2019 Red Hat Inc
      5 *
      6 * Authors:
      7 *   David Hildenbrand <david@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#include "qemu/osdep.h"
     13#include "cpu.h"
     14#include "s390x-internal.h"
     15#include "vec.h"
     16#include "tcg/tcg.h"
     17#include "tcg/tcg-gvec-desc.h"
     18#include "exec/helper-proto.h"
     19#include "exec/cpu_ldst.h"
     20#include "exec/exec-all.h"
     21
     22void HELPER(gvec_vbperm)(void *v1, const void *v2, const void *v3,
     23                         uint32_t desc)
     24{
     25    S390Vector tmp = {};
     26    uint16_t result = 0;
     27    int i;
     28
     29    for (i = 0; i < 16; i++) {
     30        const uint8_t bit_nr = s390_vec_read_element8(v3, i);
     31        uint16_t bit;
     32
     33        if (bit_nr >= 128) {
     34            continue;
     35        }
     36        bit = (s390_vec_read_element8(v2, bit_nr / 8)
     37               >> (7 - (bit_nr % 8))) & 1;
     38        result |= (bit << (15 - i));
     39    }
     40    s390_vec_write_element16(&tmp, 3, result);
     41    *(S390Vector *)v1 = tmp;
     42}
     43
     44void HELPER(vll)(CPUS390XState *env, void *v1, uint64_t addr, uint64_t bytes)
     45{
     46    if (likely(bytes >= 16)) {
     47        uint64_t t0, t1;
     48
     49        t0 = cpu_ldq_data_ra(env, addr, GETPC());
     50        addr = wrap_address(env, addr + 8);
     51        t1 = cpu_ldq_data_ra(env, addr, GETPC());
     52        s390_vec_write_element64(v1, 0, t0);
     53        s390_vec_write_element64(v1, 1, t1);
     54    } else {
     55        S390Vector tmp = {};
     56        int i;
     57
     58        for (i = 0; i < bytes; i++) {
     59            uint8_t byte = cpu_ldub_data_ra(env, addr, GETPC());
     60
     61            s390_vec_write_element8(&tmp, i, byte);
     62            addr = wrap_address(env, addr + 1);
     63        }
     64        *(S390Vector *)v1 = tmp;
     65    }
     66}
     67
     68#define DEF_VPK_HFN(BITS, TBITS)                                               \
     69typedef uint##TBITS##_t (*vpk##BITS##_fn)(uint##BITS##_t, int *);              \
     70static int vpk##BITS##_hfn(S390Vector *v1, const S390Vector *v2,               \
     71                           const S390Vector *v3, vpk##BITS##_fn fn)            \
     72{                                                                              \
     73    int i, saturated = 0;                                                      \
     74    S390Vector tmp;                                                            \
     75                                                                               \
     76    for (i = 0; i < (128 / TBITS); i++) {                                      \
     77        uint##BITS##_t src;                                                    \
     78                                                                               \
     79        if (i < (128 / BITS)) {                                                \
     80            src = s390_vec_read_element##BITS(v2, i);                          \
     81        } else {                                                               \
     82            src = s390_vec_read_element##BITS(v3, i - (128 / BITS));           \
     83        }                                                                      \
     84        s390_vec_write_element##TBITS(&tmp, i, fn(src, &saturated));           \
     85    }                                                                          \
     86    *v1 = tmp;                                                                 \
     87    return saturated;                                                          \
     88}
     89DEF_VPK_HFN(64, 32)
     90DEF_VPK_HFN(32, 16)
     91DEF_VPK_HFN(16, 8)
     92
     93#define DEF_VPK(BITS, TBITS)                                                   \
     94static uint##TBITS##_t vpk##BITS##e(uint##BITS##_t src, int *saturated)        \
     95{                                                                              \
     96    return src;                                                                \
     97}                                                                              \
     98void HELPER(gvec_vpk##BITS)(void *v1, const void *v2, const void *v3,          \
     99                            uint32_t desc)                                     \
    100{                                                                              \
    101    vpk##BITS##_hfn(v1, v2, v3, vpk##BITS##e);                                 \
    102}
    103DEF_VPK(64, 32)
    104DEF_VPK(32, 16)
    105DEF_VPK(16, 8)
    106
    107#define DEF_VPKS(BITS, TBITS)                                                  \
    108static uint##TBITS##_t vpks##BITS##e(uint##BITS##_t src, int *saturated)       \
    109{                                                                              \
    110    if ((int##BITS##_t)src > INT##TBITS##_MAX) {                               \
    111        (*saturated)++;                                                        \
    112        return INT##TBITS##_MAX;                                               \
    113    } else if ((int##BITS##_t)src < INT##TBITS##_MIN) {                        \
    114        (*saturated)++;                                                        \
    115        return INT##TBITS##_MIN;                                               \
    116    }                                                                          \
    117    return src;                                                                \
    118}                                                                              \
    119void HELPER(gvec_vpks##BITS)(void *v1, const void *v2, const void *v3,         \
    120                             uint32_t desc)                                    \
    121{                                                                              \
    122    vpk##BITS##_hfn(v1, v2, v3, vpks##BITS##e);                                \
    123}                                                                              \
    124void HELPER(gvec_vpks_cc##BITS)(void *v1, const void *v2, const void *v3,      \
    125                                CPUS390XState *env, uint32_t desc)             \
    126{                                                                              \
    127    int saturated = vpk##BITS##_hfn(v1, v2, v3, vpks##BITS##e);                \
    128                                                                               \
    129    if (saturated == (128 / TBITS)) {                                          \
    130        env->cc_op = 3;                                                        \
    131    } else if (saturated) {                                                    \
    132        env->cc_op = 1;                                                        \
    133    } else {                                                                   \
    134        env->cc_op = 0;                                                        \
    135    }                                                                          \
    136}
    137DEF_VPKS(64, 32)
    138DEF_VPKS(32, 16)
    139DEF_VPKS(16, 8)
    140
    141#define DEF_VPKLS(BITS, TBITS)                                                 \
    142static uint##TBITS##_t vpkls##BITS##e(uint##BITS##_t src, int *saturated)      \
    143{                                                                              \
    144    if (src > UINT##TBITS##_MAX) {                                             \
    145        (*saturated)++;                                                        \
    146        return UINT##TBITS##_MAX;                                              \
    147    }                                                                          \
    148    return src;                                                                \
    149}                                                                              \
    150void HELPER(gvec_vpkls##BITS)(void *v1, const void *v2, const void *v3,        \
    151                              uint32_t desc)                                   \
    152{                                                                              \
    153    vpk##BITS##_hfn(v1, v2, v3, vpkls##BITS##e);                               \
    154}                                                                              \
    155void HELPER(gvec_vpkls_cc##BITS)(void *v1, const void *v2, const void *v3,     \
    156                                 CPUS390XState *env, uint32_t desc)            \
    157{                                                                              \
    158    int saturated = vpk##BITS##_hfn(v1, v2, v3, vpkls##BITS##e);               \
    159                                                                               \
    160    if (saturated == (128 / TBITS)) {                                          \
    161        env->cc_op = 3;                                                        \
    162    } else if (saturated) {                                                    \
    163        env->cc_op = 1;                                                        \
    164    } else {                                                                   \
    165        env->cc_op = 0;                                                        \
    166    }                                                                          \
    167}
    168DEF_VPKLS(64, 32)
    169DEF_VPKLS(32, 16)
    170DEF_VPKLS(16, 8)
    171
    172void HELPER(gvec_vperm)(void *v1, const void *v2, const void *v3,
    173                        const void *v4, uint32_t desc)
    174{
    175    S390Vector tmp;
    176    int i;
    177
    178    for (i = 0; i < 16; i++) {
    179        const uint8_t selector = s390_vec_read_element8(v4, i) & 0x1f;
    180        uint8_t byte;
    181
    182        if (selector < 16) {
    183            byte = s390_vec_read_element8(v2, selector);
    184        } else {
    185            byte = s390_vec_read_element8(v3, selector - 16);
    186        }
    187        s390_vec_write_element8(&tmp, i, byte);
    188    }
    189    *(S390Vector *)v1 = tmp;
    190}
    191
    192void HELPER(vstl)(CPUS390XState *env, const void *v1, uint64_t addr,
    193                  uint64_t bytes)
    194{
    195    /* Probe write access before actually modifying memory */
    196    probe_write_access(env, addr, bytes, GETPC());
    197
    198    if (likely(bytes >= 16)) {
    199        cpu_stq_data_ra(env, addr, s390_vec_read_element64(v1, 0), GETPC());
    200        addr = wrap_address(env, addr + 8);
    201        cpu_stq_data_ra(env, addr, s390_vec_read_element64(v1, 1), GETPC());
    202    } else {
    203        S390Vector tmp = {};
    204        int i;
    205
    206        for (i = 0; i < bytes; i++) {
    207            uint8_t byte = s390_vec_read_element8(v1, i);
    208
    209            cpu_stb_data_ra(env, addr, byte, GETPC());
    210            addr = wrap_address(env, addr + 1);
    211        }
    212        *(S390Vector *)v1 = tmp;
    213    }
    214}