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 (8534B)


      1/*
      2 * QEMU SuperH CPU
      3 *
      4 * Copyright (c) 2005 Samuel Tardieu
      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 "migration/vmstate.h"
     27#include "exec/exec-all.h"
     28#include "fpu/softfloat-helpers.h"
     29
     30static void superh_cpu_set_pc(CPUState *cs, vaddr value)
     31{
     32    SuperHCPU *cpu = SUPERH_CPU(cs);
     33
     34    cpu->env.pc = value;
     35}
     36
     37static void superh_cpu_synchronize_from_tb(CPUState *cs,
     38                                           const TranslationBlock *tb)
     39{
     40    SuperHCPU *cpu = SUPERH_CPU(cs);
     41
     42    cpu->env.pc = tb->pc;
     43    cpu->env.flags = tb->flags & TB_FLAG_ENVFLAGS_MASK;
     44}
     45
     46#ifndef CONFIG_USER_ONLY
     47static bool superh_io_recompile_replay_branch(CPUState *cs,
     48                                              const TranslationBlock *tb)
     49{
     50    SuperHCPU *cpu = SUPERH_CPU(cs);
     51    CPUSH4State *env = &cpu->env;
     52
     53    if ((env->flags & ((DELAY_SLOT | DELAY_SLOT_CONDITIONAL))) != 0
     54        && env->pc != tb->pc) {
     55        env->pc -= 2;
     56        env->flags &= ~(DELAY_SLOT | DELAY_SLOT_CONDITIONAL);
     57        return true;
     58    }
     59    return false;
     60}
     61#endif
     62
     63static bool superh_cpu_has_work(CPUState *cs)
     64{
     65    return cs->interrupt_request & CPU_INTERRUPT_HARD;
     66}
     67
     68static void superh_cpu_reset(DeviceState *dev)
     69{
     70    CPUState *s = CPU(dev);
     71    SuperHCPU *cpu = SUPERH_CPU(s);
     72    SuperHCPUClass *scc = SUPERH_CPU_GET_CLASS(cpu);
     73    CPUSH4State *env = &cpu->env;
     74
     75    scc->parent_reset(dev);
     76
     77    memset(env, 0, offsetof(CPUSH4State, end_reset_fields));
     78
     79    env->pc = 0xA0000000;
     80#if defined(CONFIG_USER_ONLY)
     81    env->fpscr = FPSCR_PR; /* value for userspace according to the kernel */
     82    set_float_rounding_mode(float_round_nearest_even, &env->fp_status); /* ?! */
     83#else
     84    env->sr = (1u << SR_MD) | (1u << SR_RB) | (1u << SR_BL) |
     85              (1u << SR_I3) | (1u << SR_I2) | (1u << SR_I1) | (1u << SR_I0);
     86    env->fpscr = FPSCR_DN | FPSCR_RM_ZERO; /* CPU reset value according to SH4 manual */
     87    set_float_rounding_mode(float_round_to_zero, &env->fp_status);
     88    set_flush_to_zero(1, &env->fp_status);
     89#endif
     90    set_default_nan_mode(1, &env->fp_status);
     91}
     92
     93static void superh_cpu_disas_set_info(CPUState *cpu, disassemble_info *info)
     94{
     95    info->mach = bfd_mach_sh4;
     96    info->print_insn = print_insn_sh;
     97}
     98
     99static void superh_cpu_list_entry(gpointer data, gpointer user_data)
    100{
    101    const char *typename = object_class_get_name(OBJECT_CLASS(data));
    102    int len = strlen(typename) - strlen(SUPERH_CPU_TYPE_SUFFIX);
    103
    104    qemu_printf("%.*s\n", len, typename);
    105}
    106
    107void sh4_cpu_list(void)
    108{
    109    GSList *list;
    110
    111    list = object_class_get_list_sorted(TYPE_SUPERH_CPU, false);
    112    g_slist_foreach(list, superh_cpu_list_entry, NULL);
    113    g_slist_free(list);
    114}
    115
    116static ObjectClass *superh_cpu_class_by_name(const char *cpu_model)
    117{
    118    ObjectClass *oc;
    119    char *s, *typename = NULL;
    120
    121    s = g_ascii_strdown(cpu_model, -1);
    122    if (strcmp(s, "any") == 0) {
    123        oc = object_class_by_name(TYPE_SH7750R_CPU);
    124        goto out;
    125    }
    126
    127    typename = g_strdup_printf(SUPERH_CPU_TYPE_NAME("%s"), s);
    128    oc = object_class_by_name(typename);
    129    if (oc != NULL && object_class_is_abstract(oc)) {
    130        oc = NULL;
    131    }
    132
    133out:
    134    g_free(s);
    135    g_free(typename);
    136    return oc;
    137}
    138
    139static void sh7750r_cpu_initfn(Object *obj)
    140{
    141    SuperHCPU *cpu = SUPERH_CPU(obj);
    142    CPUSH4State *env = &cpu->env;
    143
    144    env->id = SH_CPU_SH7750R;
    145    env->features = SH_FEATURE_BCR3_AND_BCR4;
    146}
    147
    148static void sh7750r_class_init(ObjectClass *oc, void *data)
    149{
    150    SuperHCPUClass *scc = SUPERH_CPU_CLASS(oc);
    151
    152    scc->pvr = 0x00050000;
    153    scc->prr = 0x00000100;
    154    scc->cvr = 0x00110000;
    155}
    156
    157static void sh7751r_cpu_initfn(Object *obj)
    158{
    159    SuperHCPU *cpu = SUPERH_CPU(obj);
    160    CPUSH4State *env = &cpu->env;
    161
    162    env->id = SH_CPU_SH7751R;
    163    env->features = SH_FEATURE_BCR3_AND_BCR4;
    164}
    165
    166static void sh7751r_class_init(ObjectClass *oc, void *data)
    167{
    168    SuperHCPUClass *scc = SUPERH_CPU_CLASS(oc);
    169
    170    scc->pvr = 0x04050005;
    171    scc->prr = 0x00000113;
    172    scc->cvr = 0x00110000; /* Neutered caches, should be 0x20480000 */
    173}
    174
    175static void sh7785_cpu_initfn(Object *obj)
    176{
    177    SuperHCPU *cpu = SUPERH_CPU(obj);
    178    CPUSH4State *env = &cpu->env;
    179
    180    env->id = SH_CPU_SH7785;
    181    env->features = SH_FEATURE_SH4A;
    182}
    183
    184static void sh7785_class_init(ObjectClass *oc, void *data)
    185{
    186    SuperHCPUClass *scc = SUPERH_CPU_CLASS(oc);
    187
    188    scc->pvr = 0x10300700;
    189    scc->prr = 0x00000200;
    190    scc->cvr = 0x71440211;
    191}
    192
    193static void superh_cpu_realizefn(DeviceState *dev, Error **errp)
    194{
    195    CPUState *cs = CPU(dev);
    196    SuperHCPUClass *scc = SUPERH_CPU_GET_CLASS(dev);
    197    Error *local_err = NULL;
    198
    199    cpu_exec_realizefn(cs, &local_err);
    200    if (local_err != NULL) {
    201        error_propagate(errp, local_err);
    202        return;
    203    }
    204
    205    cpu_reset(cs);
    206    qemu_init_vcpu(cs);
    207
    208    scc->parent_realize(dev, errp);
    209}
    210
    211static void superh_cpu_initfn(Object *obj)
    212{
    213    SuperHCPU *cpu = SUPERH_CPU(obj);
    214    CPUSH4State *env = &cpu->env;
    215
    216    cpu_set_cpustate_pointers(cpu);
    217
    218    env->movcal_backup_tail = &(env->movcal_backup);
    219}
    220
    221#ifndef CONFIG_USER_ONLY
    222static const VMStateDescription vmstate_sh_cpu = {
    223    .name = "cpu",
    224    .unmigratable = 1,
    225};
    226
    227#include "hw/core/sysemu-cpu-ops.h"
    228
    229static const struct SysemuCPUOps sh4_sysemu_ops = {
    230    .get_phys_page_debug = superh_cpu_get_phys_page_debug,
    231};
    232#endif
    233
    234#include "hw/core/tcg-cpu-ops.h"
    235
    236static const struct TCGCPUOps superh_tcg_ops = {
    237    .initialize = sh4_translate_init,
    238    .synchronize_from_tb = superh_cpu_synchronize_from_tb,
    239    .tlb_fill = superh_cpu_tlb_fill,
    240
    241#ifndef CONFIG_USER_ONLY
    242    .cpu_exec_interrupt = superh_cpu_exec_interrupt,
    243    .do_interrupt = superh_cpu_do_interrupt,
    244    .do_unaligned_access = superh_cpu_do_unaligned_access,
    245    .io_recompile_replay_branch = superh_io_recompile_replay_branch,
    246#endif /* !CONFIG_USER_ONLY */
    247};
    248
    249static void superh_cpu_class_init(ObjectClass *oc, void *data)
    250{
    251    DeviceClass *dc = DEVICE_CLASS(oc);
    252    CPUClass *cc = CPU_CLASS(oc);
    253    SuperHCPUClass *scc = SUPERH_CPU_CLASS(oc);
    254
    255    device_class_set_parent_realize(dc, superh_cpu_realizefn,
    256                                    &scc->parent_realize);
    257
    258    device_class_set_parent_reset(dc, superh_cpu_reset, &scc->parent_reset);
    259
    260    cc->class_by_name = superh_cpu_class_by_name;
    261    cc->has_work = superh_cpu_has_work;
    262    cc->dump_state = superh_cpu_dump_state;
    263    cc->set_pc = superh_cpu_set_pc;
    264    cc->gdb_read_register = superh_cpu_gdb_read_register;
    265    cc->gdb_write_register = superh_cpu_gdb_write_register;
    266#ifndef CONFIG_USER_ONLY
    267    cc->sysemu_ops = &sh4_sysemu_ops;
    268    dc->vmsd = &vmstate_sh_cpu;
    269#endif
    270    cc->disas_set_info = superh_cpu_disas_set_info;
    271
    272    cc->gdb_num_core_regs = 59;
    273    cc->tcg_ops = &superh_tcg_ops;
    274}
    275
    276#define DEFINE_SUPERH_CPU_TYPE(type_name, cinit, initfn) \
    277    {                                                    \
    278        .name = type_name,                               \
    279        .parent = TYPE_SUPERH_CPU,                       \
    280        .class_init = cinit,                             \
    281        .instance_init = initfn,                         \
    282    }
    283static const TypeInfo superh_cpu_type_infos[] = {
    284    {
    285        .name = TYPE_SUPERH_CPU,
    286        .parent = TYPE_CPU,
    287        .instance_size = sizeof(SuperHCPU),
    288        .instance_init = superh_cpu_initfn,
    289        .abstract = true,
    290        .class_size = sizeof(SuperHCPUClass),
    291        .class_init = superh_cpu_class_init,
    292    },
    293    DEFINE_SUPERH_CPU_TYPE(TYPE_SH7750R_CPU, sh7750r_class_init,
    294                           sh7750r_cpu_initfn),
    295    DEFINE_SUPERH_CPU_TYPE(TYPE_SH7751R_CPU, sh7751r_class_init,
    296                           sh7751r_cpu_initfn),
    297    DEFINE_SUPERH_CPU_TYPE(TYPE_SH7785_CPU, sh7785_class_init,
    298                           sh7785_cpu_initfn),
    299
    300};
    301
    302DEFINE_TYPES(superh_cpu_type_infos)