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

cpu.c (8397B)


      1/*
      2 * QEMU Alpha CPU
      3 *
      4 * Copyright (c) 2007 Jocelyn Mayer
      5 * Copyright (c) 2012 SUSE LINUX Products GmbH
      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
     19 * <http://www.gnu.org/licenses/lgpl-2.1.html>
     20 */
     21
     22#include "qemu/osdep.h"
     23#include "qapi/error.h"
     24#include "qemu/qemu-print.h"
     25#include "cpu.h"
     26#include "exec/exec-all.h"
     27
     28
     29static void alpha_cpu_set_pc(CPUState *cs, vaddr value)
     30{
     31    AlphaCPU *cpu = ALPHA_CPU(cs);
     32
     33    cpu->env.pc = value;
     34}
     35
     36static bool alpha_cpu_has_work(CPUState *cs)
     37{
     38    /* Here we are checking to see if the CPU should wake up from HALT.
     39       We will have gotten into this state only for WTINT from PALmode.  */
     40    /* ??? I'm not sure how the IPL state works with WTINT to keep a CPU
     41       asleep even if (some) interrupts have been asserted.  For now,
     42       assume that if a CPU really wants to stay asleep, it will mask
     43       interrupts at the chipset level, which will prevent these bits
     44       from being set in the first place.  */
     45    return cs->interrupt_request & (CPU_INTERRUPT_HARD
     46                                    | CPU_INTERRUPT_TIMER
     47                                    | CPU_INTERRUPT_SMP
     48                                    | CPU_INTERRUPT_MCHK);
     49}
     50
     51static void alpha_cpu_disas_set_info(CPUState *cpu, disassemble_info *info)
     52{
     53    info->mach = bfd_mach_alpha_ev6;
     54    info->print_insn = print_insn_alpha;
     55}
     56
     57static void alpha_cpu_realizefn(DeviceState *dev, Error **errp)
     58{
     59    CPUState *cs = CPU(dev);
     60    AlphaCPUClass *acc = ALPHA_CPU_GET_CLASS(dev);
     61    Error *local_err = NULL;
     62
     63    cpu_exec_realizefn(cs, &local_err);
     64    if (local_err != NULL) {
     65        error_propagate(errp, local_err);
     66        return;
     67    }
     68
     69    qemu_init_vcpu(cs);
     70
     71    acc->parent_realize(dev, errp);
     72}
     73
     74static void alpha_cpu_list_entry(gpointer data, gpointer user_data)
     75{
     76    ObjectClass *oc = data;
     77
     78    qemu_printf("  %s\n", object_class_get_name(oc));
     79}
     80
     81void alpha_cpu_list(void)
     82{
     83    GSList *list;
     84
     85    list = object_class_get_list_sorted(TYPE_ALPHA_CPU, false);
     86    qemu_printf("Available CPUs:\n");
     87    g_slist_foreach(list, alpha_cpu_list_entry, NULL);
     88    g_slist_free(list);
     89}
     90
     91/* Models */
     92typedef struct AlphaCPUAlias {
     93    const char *alias;
     94    const char *typename;
     95} AlphaCPUAlias;
     96
     97static const AlphaCPUAlias alpha_cpu_aliases[] = {
     98    { "21064",   ALPHA_CPU_TYPE_NAME("ev4") },
     99    { "21164",   ALPHA_CPU_TYPE_NAME("ev5") },
    100    { "21164a",  ALPHA_CPU_TYPE_NAME("ev56") },
    101    { "21164pc", ALPHA_CPU_TYPE_NAME("pca56") },
    102    { "21264",   ALPHA_CPU_TYPE_NAME("ev6") },
    103    { "21264a",  ALPHA_CPU_TYPE_NAME("ev67") },
    104};
    105
    106static ObjectClass *alpha_cpu_class_by_name(const char *cpu_model)
    107{
    108    ObjectClass *oc;
    109    char *typename;
    110    int i;
    111
    112    oc = object_class_by_name(cpu_model);
    113    if (oc != NULL && object_class_dynamic_cast(oc, TYPE_ALPHA_CPU) != NULL &&
    114        !object_class_is_abstract(oc)) {
    115        return oc;
    116    }
    117
    118    for (i = 0; i < ARRAY_SIZE(alpha_cpu_aliases); i++) {
    119        if (strcmp(cpu_model, alpha_cpu_aliases[i].alias) == 0) {
    120            oc = object_class_by_name(alpha_cpu_aliases[i].typename);
    121            assert(oc != NULL && !object_class_is_abstract(oc));
    122            return oc;
    123        }
    124    }
    125
    126    typename = g_strdup_printf(ALPHA_CPU_TYPE_NAME("%s"), cpu_model);
    127    oc = object_class_by_name(typename);
    128    g_free(typename);
    129    if (oc != NULL && object_class_is_abstract(oc)) {
    130        oc = NULL;
    131    }
    132
    133    /* TODO: remove match everything nonsense */
    134    /* Default to ev67; no reason not to emulate insns by default. */
    135    if (!oc) {
    136        oc = object_class_by_name(ALPHA_CPU_TYPE_NAME("ev67"));
    137    }
    138
    139    return oc;
    140}
    141
    142static void ev4_cpu_initfn(Object *obj)
    143{
    144    AlphaCPU *cpu = ALPHA_CPU(obj);
    145    CPUAlphaState *env = &cpu->env;
    146
    147    env->implver = IMPLVER_2106x;
    148}
    149
    150static void ev5_cpu_initfn(Object *obj)
    151{
    152    AlphaCPU *cpu = ALPHA_CPU(obj);
    153    CPUAlphaState *env = &cpu->env;
    154
    155    env->implver = IMPLVER_21164;
    156}
    157
    158static void ev56_cpu_initfn(Object *obj)
    159{
    160    AlphaCPU *cpu = ALPHA_CPU(obj);
    161    CPUAlphaState *env = &cpu->env;
    162
    163    env->amask |= AMASK_BWX;
    164}
    165
    166static void pca56_cpu_initfn(Object *obj)
    167{
    168    AlphaCPU *cpu = ALPHA_CPU(obj);
    169    CPUAlphaState *env = &cpu->env;
    170
    171    env->amask |= AMASK_MVI;
    172}
    173
    174static void ev6_cpu_initfn(Object *obj)
    175{
    176    AlphaCPU *cpu = ALPHA_CPU(obj);
    177    CPUAlphaState *env = &cpu->env;
    178
    179    env->implver = IMPLVER_21264;
    180    env->amask = AMASK_BWX | AMASK_FIX | AMASK_MVI | AMASK_TRAP;
    181}
    182
    183static void ev67_cpu_initfn(Object *obj)
    184{
    185    AlphaCPU *cpu = ALPHA_CPU(obj);
    186    CPUAlphaState *env = &cpu->env;
    187
    188    env->amask |= AMASK_CIX | AMASK_PREFETCH;
    189}
    190
    191static void alpha_cpu_initfn(Object *obj)
    192{
    193    AlphaCPU *cpu = ALPHA_CPU(obj);
    194    CPUAlphaState *env = &cpu->env;
    195
    196    cpu_set_cpustate_pointers(cpu);
    197
    198    env->lock_addr = -1;
    199#if defined(CONFIG_USER_ONLY)
    200    env->flags = ENV_FLAG_PS_USER | ENV_FLAG_FEN;
    201    cpu_alpha_store_fpcr(env, (uint64_t)(FPCR_INVD | FPCR_DZED | FPCR_OVFD
    202                                         | FPCR_UNFD | FPCR_INED | FPCR_DNOD
    203                                         | FPCR_DYN_NORMAL) << 32);
    204#else
    205    env->flags = ENV_FLAG_PAL_MODE | ENV_FLAG_FEN;
    206#endif
    207}
    208
    209#ifndef CONFIG_USER_ONLY
    210#include "hw/core/sysemu-cpu-ops.h"
    211
    212static const struct SysemuCPUOps alpha_sysemu_ops = {
    213    .get_phys_page_debug = alpha_cpu_get_phys_page_debug,
    214};
    215#endif
    216
    217#include "hw/core/tcg-cpu-ops.h"
    218
    219static const struct TCGCPUOps alpha_tcg_ops = {
    220    .initialize = alpha_translate_init,
    221    .tlb_fill = alpha_cpu_tlb_fill,
    222
    223#ifndef CONFIG_USER_ONLY
    224    .cpu_exec_interrupt = alpha_cpu_exec_interrupt,
    225    .do_interrupt = alpha_cpu_do_interrupt,
    226    .do_transaction_failed = alpha_cpu_do_transaction_failed,
    227    .do_unaligned_access = alpha_cpu_do_unaligned_access,
    228#endif /* !CONFIG_USER_ONLY */
    229};
    230
    231static void alpha_cpu_class_init(ObjectClass *oc, void *data)
    232{
    233    DeviceClass *dc = DEVICE_CLASS(oc);
    234    CPUClass *cc = CPU_CLASS(oc);
    235    AlphaCPUClass *acc = ALPHA_CPU_CLASS(oc);
    236
    237    device_class_set_parent_realize(dc, alpha_cpu_realizefn,
    238                                    &acc->parent_realize);
    239
    240    cc->class_by_name = alpha_cpu_class_by_name;
    241    cc->has_work = alpha_cpu_has_work;
    242    cc->dump_state = alpha_cpu_dump_state;
    243    cc->set_pc = alpha_cpu_set_pc;
    244    cc->gdb_read_register = alpha_cpu_gdb_read_register;
    245    cc->gdb_write_register = alpha_cpu_gdb_write_register;
    246#ifndef CONFIG_USER_ONLY
    247    dc->vmsd = &vmstate_alpha_cpu;
    248    cc->sysemu_ops = &alpha_sysemu_ops;
    249#endif
    250    cc->disas_set_info = alpha_cpu_disas_set_info;
    251
    252    cc->tcg_ops = &alpha_tcg_ops;
    253    cc->gdb_num_core_regs = 67;
    254}
    255
    256#define DEFINE_ALPHA_CPU_TYPE(base_type, cpu_model, initfn) \
    257     {                                                      \
    258         .parent = base_type,                               \
    259         .instance_init = initfn,                           \
    260         .name = ALPHA_CPU_TYPE_NAME(cpu_model),            \
    261     }
    262
    263static const TypeInfo alpha_cpu_type_infos[] = {
    264    {
    265        .name = TYPE_ALPHA_CPU,
    266        .parent = TYPE_CPU,
    267        .instance_size = sizeof(AlphaCPU),
    268        .instance_init = alpha_cpu_initfn,
    269        .abstract = true,
    270        .class_size = sizeof(AlphaCPUClass),
    271        .class_init = alpha_cpu_class_init,
    272    },
    273    DEFINE_ALPHA_CPU_TYPE(TYPE_ALPHA_CPU, "ev4", ev4_cpu_initfn),
    274    DEFINE_ALPHA_CPU_TYPE(TYPE_ALPHA_CPU, "ev5", ev5_cpu_initfn),
    275    DEFINE_ALPHA_CPU_TYPE(ALPHA_CPU_TYPE_NAME("ev5"), "ev56", ev56_cpu_initfn),
    276    DEFINE_ALPHA_CPU_TYPE(ALPHA_CPU_TYPE_NAME("ev56"), "pca56",
    277                          pca56_cpu_initfn),
    278    DEFINE_ALPHA_CPU_TYPE(TYPE_ALPHA_CPU, "ev6", ev6_cpu_initfn),
    279    DEFINE_ALPHA_CPU_TYPE(ALPHA_CPU_TYPE_NAME("ev6"), "ev67", ev67_cpu_initfn),
    280    DEFINE_ALPHA_CPU_TYPE(ALPHA_CPU_TYPE_NAME("ev67"), "ev68", NULL),
    281};
    282
    283DEFINE_TYPES(alpha_cpu_type_infos)