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

special_helper.c (4888B)


      1/*
      2 *  QEMU MIPS emulation: Special opcode helpers
      3 *
      4 *  Copyright (c) 2004-2005 Jocelyn Mayer
      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
     21#include "qemu/osdep.h"
     22#include "cpu.h"
     23#include "exec/helper-proto.h"
     24#include "exec/exec-all.h"
     25#include "internal.h"
     26
     27/* Specials */
     28target_ulong helper_di(CPUMIPSState *env)
     29{
     30    target_ulong t0 = env->CP0_Status;
     31
     32    env->CP0_Status = t0 & ~(1 << CP0St_IE);
     33    return t0;
     34}
     35
     36target_ulong helper_ei(CPUMIPSState *env)
     37{
     38    target_ulong t0 = env->CP0_Status;
     39
     40    env->CP0_Status = t0 | (1 << CP0St_IE);
     41    return t0;
     42}
     43
     44static void debug_pre_eret(CPUMIPSState *env)
     45{
     46    if (qemu_loglevel_mask(CPU_LOG_EXEC)) {
     47        qemu_log("ERET: PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx,
     48                env->active_tc.PC, env->CP0_EPC);
     49        if (env->CP0_Status & (1 << CP0St_ERL)) {
     50            qemu_log(" ErrorEPC " TARGET_FMT_lx, env->CP0_ErrorEPC);
     51        }
     52        if (env->hflags & MIPS_HFLAG_DM) {
     53            qemu_log(" DEPC " TARGET_FMT_lx, env->CP0_DEPC);
     54        }
     55        qemu_log("\n");
     56    }
     57}
     58
     59static void debug_post_eret(CPUMIPSState *env)
     60{
     61    if (qemu_loglevel_mask(CPU_LOG_EXEC)) {
     62        qemu_log("  =>  PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx,
     63                env->active_tc.PC, env->CP0_EPC);
     64        if (env->CP0_Status & (1 << CP0St_ERL)) {
     65            qemu_log(" ErrorEPC " TARGET_FMT_lx, env->CP0_ErrorEPC);
     66        }
     67        if (env->hflags & MIPS_HFLAG_DM) {
     68            qemu_log(" DEPC " TARGET_FMT_lx, env->CP0_DEPC);
     69        }
     70        switch (cpu_mmu_index(env, false)) {
     71        case 3:
     72            qemu_log(", ERL\n");
     73            break;
     74        case MIPS_HFLAG_UM:
     75            qemu_log(", UM\n");
     76            break;
     77        case MIPS_HFLAG_SM:
     78            qemu_log(", SM\n");
     79            break;
     80        case MIPS_HFLAG_KM:
     81            qemu_log("\n");
     82            break;
     83        default:
     84            cpu_abort(env_cpu(env), "Invalid MMU mode!\n");
     85            break;
     86        }
     87    }
     88}
     89
     90bool mips_io_recompile_replay_branch(CPUState *cs, const TranslationBlock *tb)
     91{
     92    MIPSCPU *cpu = MIPS_CPU(cs);
     93    CPUMIPSState *env = &cpu->env;
     94
     95    if ((env->hflags & MIPS_HFLAG_BMASK) != 0
     96        && env->active_tc.PC != tb->pc) {
     97        env->active_tc.PC -= (env->hflags & MIPS_HFLAG_B16 ? 2 : 4);
     98        env->hflags &= ~MIPS_HFLAG_BMASK;
     99        return true;
    100    }
    101    return false;
    102}
    103
    104static inline void exception_return(CPUMIPSState *env)
    105{
    106    debug_pre_eret(env);
    107    if (env->CP0_Status & (1 << CP0St_ERL)) {
    108        mips_env_set_pc(env, env->CP0_ErrorEPC);
    109        env->CP0_Status &= ~(1 << CP0St_ERL);
    110    } else {
    111        mips_env_set_pc(env, env->CP0_EPC);
    112        env->CP0_Status &= ~(1 << CP0St_EXL);
    113    }
    114    compute_hflags(env);
    115    debug_post_eret(env);
    116}
    117
    118void helper_eret(CPUMIPSState *env)
    119{
    120    exception_return(env);
    121    env->CP0_LLAddr = 1;
    122    env->lladdr = 1;
    123}
    124
    125void helper_eretnc(CPUMIPSState *env)
    126{
    127    exception_return(env);
    128}
    129
    130void helper_deret(CPUMIPSState *env)
    131{
    132    debug_pre_eret(env);
    133
    134    env->hflags &= ~MIPS_HFLAG_DM;
    135    compute_hflags(env);
    136
    137    mips_env_set_pc(env, env->CP0_DEPC);
    138
    139    debug_post_eret(env);
    140}
    141
    142void helper_cache(CPUMIPSState *env, target_ulong addr, uint32_t op)
    143{
    144    static const char *const type_name[] = {
    145        "Primary Instruction",
    146        "Primary Data or Unified Primary",
    147        "Tertiary",
    148        "Secondary"
    149    };
    150    uint32_t cache_type = extract32(op, 0, 2);
    151    uint32_t cache_operation = extract32(op, 2, 3);
    152    target_ulong index = addr & 0x1fffffff;
    153
    154    switch (cache_operation) {
    155    case 0b010: /* Index Store Tag */
    156        memory_region_dispatch_write(env->itc_tag, index, env->CP0_TagLo,
    157                                     MO_64, MEMTXATTRS_UNSPECIFIED);
    158        break;
    159    case 0b001: /* Index Load Tag */
    160        memory_region_dispatch_read(env->itc_tag, index, &env->CP0_TagLo,
    161                                    MO_64, MEMTXATTRS_UNSPECIFIED);
    162        break;
    163    case 0b000: /* Index Invalidate */
    164    case 0b100: /* Hit Invalidate */
    165    case 0b110: /* Hit Writeback */
    166        /* no-op */
    167        break;
    168    default:
    169        qemu_log_mask(LOG_UNIMP, "cache operation:%u (type: %s cache)\n",
    170                      cache_operation, type_name[cache_type]);
    171        break;
    172    }
    173}