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

helper.c (8926B)


      1/*
      2 *  CRIS helper routines.
      3 *
      4 *  Copyright (c) 2007 AXIS Communications AB
      5 *  Written by Edgar E. Iglesias.
      6 *
      7 * This library is free software; you can redistribute it and/or
      8 * modify it under the terms of the GNU Lesser General Public
      9 * License as published by the Free Software Foundation; either
     10 * version 2.1 of the License, or (at your option) any later version.
     11 *
     12 * This library is distributed in the hope that it will be useful,
     13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     15 * Lesser General Public License for more details.
     16 *
     17 * You should have received a copy of the GNU Lesser General Public
     18 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
     19 */
     20
     21#include "qemu/osdep.h"
     22#include "cpu.h"
     23#include "hw/core/tcg-cpu-ops.h"
     24#include "mmu.h"
     25#include "qemu/host-utils.h"
     26#include "exec/exec-all.h"
     27#include "exec/cpu_ldst.h"
     28#include "exec/helper-proto.h"
     29
     30
     31//#define CRIS_HELPER_DEBUG
     32
     33
     34#ifdef CRIS_HELPER_DEBUG
     35#define D(x) x
     36#define D_LOG(...) qemu_log(__VA_ARGS__)
     37#else
     38#define D(x)
     39#define D_LOG(...) do { } while (0)
     40#endif
     41
     42#if defined(CONFIG_USER_ONLY)
     43
     44bool cris_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
     45                       MMUAccessType access_type, int mmu_idx,
     46                       bool probe, uintptr_t retaddr)
     47{
     48    CRISCPU *cpu = CRIS_CPU(cs);
     49
     50    cs->exception_index = 0xaa;
     51    cpu->env.pregs[PR_EDA] = address;
     52    cpu_loop_exit_restore(cs, retaddr);
     53}
     54
     55#else /* !CONFIG_USER_ONLY */
     56
     57
     58static void cris_shift_ccs(CPUCRISState *env)
     59{
     60    uint32_t ccs;
     61    /* Apply the ccs shift.  */
     62    ccs = env->pregs[PR_CCS];
     63    ccs = ((ccs & 0xc0000000) | ((ccs << 12) >> 2)) & ~0x3ff;
     64    env->pregs[PR_CCS] = ccs;
     65}
     66
     67bool cris_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
     68                       MMUAccessType access_type, int mmu_idx,
     69                       bool probe, uintptr_t retaddr)
     70{
     71    CRISCPU *cpu = CRIS_CPU(cs);
     72    CPUCRISState *env = &cpu->env;
     73    struct cris_mmu_result res;
     74    int prot, miss;
     75    target_ulong phy;
     76
     77    miss = cris_mmu_translate(&res, env, address & TARGET_PAGE_MASK,
     78                              access_type, mmu_idx, 0);
     79    if (likely(!miss)) {
     80        /*
     81         * Mask off the cache selection bit. The ETRAX busses do not
     82         * see the top bit.
     83         */
     84        phy = res.phy & ~0x80000000;
     85        prot = res.prot;
     86        tlb_set_page(cs, address & TARGET_PAGE_MASK, phy,
     87                     prot, mmu_idx, TARGET_PAGE_SIZE);
     88        return true;
     89    }
     90
     91    if (probe) {
     92        return false;
     93    }
     94
     95    if (cs->exception_index == EXCP_BUSFAULT) {
     96        cpu_abort(cs, "CRIS: Illegal recursive bus fault."
     97                      "addr=%" VADDR_PRIx " access_type=%d\n",
     98                      address, access_type);
     99    }
    100
    101    env->pregs[PR_EDA] = address;
    102    cs->exception_index = EXCP_BUSFAULT;
    103    env->fault_vector = res.bf_vec;
    104    if (retaddr) {
    105        if (cpu_restore_state(cs, retaddr, true)) {
    106            /* Evaluate flags after retranslation. */
    107            helper_top_evaluate_flags(env);
    108        }
    109    }
    110    cpu_loop_exit(cs);
    111}
    112
    113void crisv10_cpu_do_interrupt(CPUState *cs)
    114{
    115    CRISCPU *cpu = CRIS_CPU(cs);
    116    CPUCRISState *env = &cpu->env;
    117    int ex_vec = -1;
    118
    119    D_LOG("exception index=%d interrupt_req=%d\n",
    120          cs->exception_index,
    121          cs->interrupt_request);
    122
    123    if (env->dslot) {
    124        /* CRISv10 never takes interrupts while in a delay-slot.  */
    125        cpu_abort(cs, "CRIS: Interrupt on delay-slot\n");
    126    }
    127
    128    assert(!(env->pregs[PR_CCS] & PFIX_FLAG));
    129    switch (cs->exception_index) {
    130    case EXCP_BREAK:
    131        /* These exceptions are genereated by the core itself.
    132           ERP should point to the insn following the brk.  */
    133        ex_vec = env->trap_vector;
    134        env->pregs[PRV10_BRP] = env->pc;
    135        break;
    136
    137    case EXCP_NMI:
    138        /* NMI is hardwired to vector zero.  */
    139        ex_vec = 0;
    140        env->pregs[PR_CCS] &= ~M_FLAG_V10;
    141        env->pregs[PRV10_BRP] = env->pc;
    142        break;
    143
    144    case EXCP_BUSFAULT:
    145        cpu_abort(cs, "Unhandled busfault");
    146        break;
    147
    148    default:
    149        /* The interrupt controller gives us the vector.  */
    150        ex_vec = env->interrupt_vector;
    151        /* Normal interrupts are taken between
    152           TB's.  env->pc is valid here.  */
    153        env->pregs[PR_ERP] = env->pc;
    154        break;
    155    }
    156
    157    if (env->pregs[PR_CCS] & U_FLAG) {
    158        /* Swap stack pointers.  */
    159        env->pregs[PR_USP] = env->regs[R_SP];
    160        env->regs[R_SP] = env->ksp;
    161    }
    162
    163    /* Now that we are in kernel mode, load the handlers address.  */
    164    env->pc = cpu_ldl_code(env, env->pregs[PR_EBP] + ex_vec * 4);
    165    env->locked_irq = 1;
    166    env->pregs[PR_CCS] |= F_FLAG_V10; /* set F.  */
    167
    168    qemu_log_mask(CPU_LOG_INT, "%s isr=%x vec=%x ccs=%x pid=%d erp=%x\n",
    169                  __func__, env->pc, ex_vec,
    170                  env->pregs[PR_CCS],
    171                  env->pregs[PR_PID],
    172                  env->pregs[PR_ERP]);
    173}
    174
    175void cris_cpu_do_interrupt(CPUState *cs)
    176{
    177    CRISCPU *cpu = CRIS_CPU(cs);
    178    CPUCRISState *env = &cpu->env;
    179    int ex_vec = -1;
    180
    181    D_LOG("exception index=%d interrupt_req=%d\n",
    182          cs->exception_index,
    183          cs->interrupt_request);
    184
    185    switch (cs->exception_index) {
    186    case EXCP_BREAK:
    187        /* These exceptions are genereated by the core itself.
    188           ERP should point to the insn following the brk.  */
    189        ex_vec = env->trap_vector;
    190        env->pregs[PR_ERP] = env->pc;
    191        break;
    192
    193    case EXCP_NMI:
    194        /* NMI is hardwired to vector zero.  */
    195        ex_vec = 0;
    196        env->pregs[PR_CCS] &= ~M_FLAG_V32;
    197        env->pregs[PR_NRP] = env->pc;
    198        break;
    199
    200    case EXCP_BUSFAULT:
    201        ex_vec = env->fault_vector;
    202        env->pregs[PR_ERP] = env->pc;
    203        break;
    204
    205    default:
    206        /* The interrupt controller gives us the vector.  */
    207        ex_vec = env->interrupt_vector;
    208        /* Normal interrupts are taken between
    209           TB's.  env->pc is valid here.  */
    210        env->pregs[PR_ERP] = env->pc;
    211        break;
    212    }
    213
    214    /* Fill in the IDX field.  */
    215    env->pregs[PR_EXS] = (ex_vec & 0xff) << 8;
    216
    217    if (env->dslot) {
    218        D_LOG("excp isr=%x PC=%x ds=%d SP=%x"
    219              " ERP=%x pid=%x ccs=%x cc=%d %x\n",
    220              ex_vec, env->pc, env->dslot,
    221              env->regs[R_SP],
    222              env->pregs[PR_ERP], env->pregs[PR_PID],
    223              env->pregs[PR_CCS],
    224              env->cc_op, env->cc_mask);
    225        /* We loose the btarget, btaken state here so rexec the
    226           branch.  */
    227        env->pregs[PR_ERP] -= env->dslot;
    228        /* Exception starts with dslot cleared.  */
    229        env->dslot = 0;
    230    }
    231
    232    if (env->pregs[PR_CCS] & U_FLAG) {
    233        /* Swap stack pointers.  */
    234        env->pregs[PR_USP] = env->regs[R_SP];
    235        env->regs[R_SP] = env->ksp;
    236    }
    237
    238    /* Apply the CRIS CCS shift. Clears U if set.  */
    239    cris_shift_ccs(env);
    240
    241    /* Now that we are in kernel mode, load the handlers address.
    242       This load may not fault, real hw leaves that behaviour as
    243       undefined.  */
    244    env->pc = cpu_ldl_code(env, env->pregs[PR_EBP] + ex_vec * 4);
    245
    246    /* Clear the excption_index to avoid spurios hw_aborts for recursive
    247       bus faults.  */
    248    cs->exception_index = -1;
    249
    250    D_LOG("%s isr=%x vec=%x ccs=%x pid=%d erp=%x\n",
    251          __func__, env->pc, ex_vec,
    252          env->pregs[PR_CCS],
    253          env->pregs[PR_PID],
    254          env->pregs[PR_ERP]);
    255}
    256
    257hwaddr cris_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
    258{
    259    CRISCPU *cpu = CRIS_CPU(cs);
    260    uint32_t phy = addr;
    261    struct cris_mmu_result res;
    262    int miss;
    263
    264    miss = cris_mmu_translate(&res, &cpu->env, addr, MMU_DATA_LOAD, 0, 1);
    265    /* If D TLB misses, try I TLB.  */
    266    if (miss) {
    267        miss = cris_mmu_translate(&res, &cpu->env, addr, MMU_INST_FETCH, 0, 1);
    268    }
    269
    270    if (!miss) {
    271        phy = res.phy;
    272    }
    273    D(fprintf(stderr, "%s %x -> %x\n", __func__, addr, phy));
    274    return phy;
    275}
    276
    277bool cris_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
    278{
    279    CPUClass *cc = CPU_GET_CLASS(cs);
    280    CRISCPU *cpu = CRIS_CPU(cs);
    281    CPUCRISState *env = &cpu->env;
    282    bool ret = false;
    283
    284    if (interrupt_request & CPU_INTERRUPT_HARD
    285        && (env->pregs[PR_CCS] & I_FLAG)
    286        && !env->locked_irq) {
    287        cs->exception_index = EXCP_IRQ;
    288        cc->tcg_ops->do_interrupt(cs);
    289        ret = true;
    290    }
    291    if (interrupt_request & CPU_INTERRUPT_NMI) {
    292        unsigned int m_flag_archval;
    293        if (env->pregs[PR_VR] < 32) {
    294            m_flag_archval = M_FLAG_V10;
    295        } else {
    296            m_flag_archval = M_FLAG_V32;
    297        }
    298        if ((env->pregs[PR_CCS] & m_flag_archval)) {
    299            cs->exception_index = EXCP_NMI;
    300            cc->tcg_ops->do_interrupt(cs);
    301            ret = true;
    302        }
    303    }
    304
    305    return ret;
    306}
    307
    308#endif /* !CONFIG_USER_ONLY */