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

misc_helper.c (4015B)


      1/*
      2 *  x86 misc helpers
      3 *
      4 *  Copyright (c) 2003 Fabrice Bellard
      5 *
      6 * This library is free software; you can redistribute it and/or
      7 * modify it under the terms of the GNU Lesser General Public
      8 * License as published by the Free Software Foundation; either
      9 * version 2.1 of the License, or (at your option) any later version.
     10 *
     11 * This library is distributed in the hope that it will be useful,
     12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     14 * Lesser General Public License for more details.
     15 *
     16 * You should have received a copy of the GNU Lesser General Public
     17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
     18 */
     19
     20#include "qemu/osdep.h"
     21#include "cpu.h"
     22#include "exec/helper-proto.h"
     23#include "exec/exec-all.h"
     24#include "helper-tcg.h"
     25
     26/*
     27 * NOTE: the translator must set DisasContext.cc_op to CC_OP_EFLAGS
     28 * after generating a call to a helper that uses this.
     29 */
     30void cpu_load_eflags(CPUX86State *env, int eflags, int update_mask)
     31{
     32    CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
     33    CC_OP = CC_OP_EFLAGS;
     34    env->df = 1 - (2 * ((eflags >> 10) & 1));
     35    env->eflags = (env->eflags & ~update_mask) |
     36        (eflags & update_mask) | 0x2;
     37}
     38
     39void helper_into(CPUX86State *env, int next_eip_addend)
     40{
     41    int eflags;
     42
     43    eflags = cpu_cc_compute_all(env, CC_OP);
     44    if (eflags & CC_O) {
     45        raise_interrupt(env, EXCP04_INTO, 1, 0, next_eip_addend);
     46    }
     47}
     48
     49void helper_cpuid(CPUX86State *env)
     50{
     51    uint32_t eax, ebx, ecx, edx;
     52
     53    cpu_svm_check_intercept_param(env, SVM_EXIT_CPUID, 0, GETPC());
     54
     55    cpu_x86_cpuid(env, (uint32_t)env->regs[R_EAX], (uint32_t)env->regs[R_ECX],
     56                  &eax, &ebx, &ecx, &edx);
     57    env->regs[R_EAX] = eax;
     58    env->regs[R_EBX] = ebx;
     59    env->regs[R_ECX] = ecx;
     60    env->regs[R_EDX] = edx;
     61}
     62
     63void helper_rdtsc(CPUX86State *env)
     64{
     65    uint64_t val;
     66
     67    if ((env->cr[4] & CR4_TSD_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) {
     68        raise_exception_ra(env, EXCP0D_GPF, GETPC());
     69    }
     70    cpu_svm_check_intercept_param(env, SVM_EXIT_RDTSC, 0, GETPC());
     71
     72    val = cpu_get_tsc(env) + env->tsc_offset;
     73    env->regs[R_EAX] = (uint32_t)(val);
     74    env->regs[R_EDX] = (uint32_t)(val >> 32);
     75}
     76
     77void helper_rdtscp(CPUX86State *env)
     78{
     79    helper_rdtsc(env);
     80    env->regs[R_ECX] = (uint32_t)(env->tsc_aux);
     81}
     82
     83void QEMU_NORETURN helper_rdpmc(CPUX86State *env)
     84{
     85    if (((env->cr[4] & CR4_PCE_MASK) == 0 ) &&
     86        ((env->hflags & HF_CPL_MASK) != 0)) {
     87        raise_exception_ra(env, EXCP0D_GPF, GETPC());
     88    }
     89    cpu_svm_check_intercept_param(env, SVM_EXIT_RDPMC, 0, GETPC());
     90
     91    /* currently unimplemented */
     92    qemu_log_mask(LOG_UNIMP, "x86: unimplemented rdpmc\n");
     93    raise_exception_err(env, EXCP06_ILLOP, 0);
     94}
     95
     96void QEMU_NORETURN do_pause(CPUX86State *env)
     97{
     98    CPUState *cs = env_cpu(env);
     99
    100    /* Just let another CPU run.  */
    101    cs->exception_index = EXCP_INTERRUPT;
    102    cpu_loop_exit(cs);
    103}
    104
    105void QEMU_NORETURN helper_pause(CPUX86State *env, int next_eip_addend)
    106{
    107    cpu_svm_check_intercept_param(env, SVM_EXIT_PAUSE, 0, GETPC());
    108    env->eip += next_eip_addend;
    109
    110    do_pause(env);
    111}
    112
    113void QEMU_NORETURN helper_debug(CPUX86State *env)
    114{
    115    CPUState *cs = env_cpu(env);
    116
    117    cs->exception_index = EXCP_DEBUG;
    118    cpu_loop_exit(cs);
    119}
    120
    121uint64_t helper_rdpkru(CPUX86State *env, uint32_t ecx)
    122{
    123    if ((env->cr[4] & CR4_PKE_MASK) == 0) {
    124        raise_exception_err_ra(env, EXCP06_ILLOP, 0, GETPC());
    125    }
    126    if (ecx != 0) {
    127        raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC());
    128    }
    129
    130    return env->pkru;
    131}
    132
    133void helper_wrpkru(CPUX86State *env, uint32_t ecx, uint64_t val)
    134{
    135    CPUState *cs = env_cpu(env);
    136
    137    if ((env->cr[4] & CR4_PKE_MASK) == 0) {
    138        raise_exception_err_ra(env, EXCP06_ILLOP, 0, GETPC());
    139    }
    140    if (ecx != 0 || (val & 0xFFFFFFFF00000000ull)) {
    141        raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC());
    142    }
    143
    144    env->pkru = val;
    145    tlb_flush(cs);
    146}