qemu/target/riscv/cpu.c
<<
>>
Prefs
   1/*
   2 * QEMU RISC-V CPU
   3 *
   4 * Copyright (c) 2016-2017 Sagar Karandikar, sagark@eecs.berkeley.edu
   5 * Copyright (c) 2017-2018 SiFive, Inc.
   6 *
   7 * This program is free software; you can redistribute it and/or modify it
   8 * under the terms and conditions of the GNU General Public License,
   9 * version 2 or later, as published by the Free Software Foundation.
  10 *
  11 * This program is distributed in the hope it will be useful, but WITHOUT
  12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  14 * more details.
  15 *
  16 * You should have received a copy of the GNU General Public License along with
  17 * this program.  If not, see <http://www.gnu.org/licenses/>.
  18 */
  19
  20#include "qemu/osdep.h"
  21#include "qemu/log.h"
  22#include "cpu.h"
  23#include "exec/exec-all.h"
  24#include "qapi/error.h"
  25#include "migration/vmstate.h"
  26
  27/* RISC-V CPU definitions */
  28
  29static const char riscv_exts[26] = "IEMAFDQCLBJTPVNSUHKORWXYZG";
  30
  31const char * const riscv_int_regnames[] = {
  32  "zero", "ra  ", "sp  ", "gp  ", "tp  ", "t0  ", "t1  ", "t2  ",
  33  "s0  ", "s1  ", "a0  ", "a1  ", "a2  ", "a3  ", "a4  ", "a5  ",
  34  "a6  ", "a7  ", "s2  ", "s3  ", "s4  ", "s5  ", "s6  ", "s7  ",
  35  "s8  ", "s9  ", "s10 ", "s11 ", "t3  ", "t4  ", "t5  ", "t6  "
  36};
  37
  38const char * const riscv_fpr_regnames[] = {
  39  "ft0 ", "ft1 ", "ft2 ", "ft3 ", "ft4 ", "ft5 ", "ft6 ",  "ft7 ",
  40  "fs0 ", "fs1 ", "fa0 ", "fa1 ", "fa2 ", "fa3 ", "fa4 ",  "fa5 ",
  41  "fa6 ", "fa7 ", "fs2 ", "fs3 ", "fs4 ", "fs5 ", "fs6 ",  "fs7 ",
  42  "fs8 ", "fs9 ", "fs10", "fs11", "ft8 ", "ft9 ", "ft10",  "ft11"
  43};
  44
  45const char * const riscv_excp_names[] = {
  46    "misaligned_fetch",
  47    "fault_fetch",
  48    "illegal_instruction",
  49    "breakpoint",
  50    "misaligned_load",
  51    "fault_load",
  52    "misaligned_store",
  53    "fault_store",
  54    "user_ecall",
  55    "supervisor_ecall",
  56    "hypervisor_ecall",
  57    "machine_ecall",
  58    "exec_page_fault",
  59    "load_page_fault",
  60    "reserved",
  61    "store_page_fault"
  62};
  63
  64const char * const riscv_intr_names[] = {
  65    "u_software",
  66    "s_software",
  67    "h_software",
  68    "m_software",
  69    "u_timer",
  70    "s_timer",
  71    "h_timer",
  72    "m_timer",
  73    "u_external",
  74    "s_external",
  75    "h_external",
  76    "m_external",
  77    "reserved",
  78    "reserved",
  79    "reserved",
  80    "reserved"
  81};
  82
  83static void set_misa(CPURISCVState *env, target_ulong misa)
  84{
  85    env->misa_mask = env->misa = misa;
  86}
  87
  88static void set_versions(CPURISCVState *env, int user_ver, int priv_ver)
  89{
  90    env->user_ver = user_ver;
  91    env->priv_ver = priv_ver;
  92}
  93
  94static void set_feature(CPURISCVState *env, int feature)
  95{
  96    env->features |= (1ULL << feature);
  97}
  98
  99static void set_resetvec(CPURISCVState *env, int resetvec)
 100{
 101#ifndef CONFIG_USER_ONLY
 102    env->resetvec = resetvec;
 103#endif
 104}
 105
 106static void riscv_any_cpu_init(Object *obj)
 107{
 108    CPURISCVState *env = &RISCV_CPU(obj)->env;
 109    set_misa(env, RVXLEN | RVI | RVM | RVA | RVF | RVD | RVC | RVU);
 110    set_versions(env, USER_VERSION_2_02_0, PRIV_VERSION_1_10_0);
 111    set_resetvec(env, DEFAULT_RSTVEC);
 112}
 113
 114#if defined(TARGET_RISCV32)
 115
 116static void rv32gcsu_priv1_09_1_cpu_init(Object *obj)
 117{
 118    CPURISCVState *env = &RISCV_CPU(obj)->env;
 119    set_misa(env, RV32 | RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU);
 120    set_versions(env, USER_VERSION_2_02_0, PRIV_VERSION_1_09_1);
 121    set_resetvec(env, DEFAULT_RSTVEC);
 122    set_feature(env, RISCV_FEATURE_MMU);
 123    set_feature(env, RISCV_FEATURE_PMP);
 124}
 125
 126static void rv32gcsu_priv1_10_0_cpu_init(Object *obj)
 127{
 128    CPURISCVState *env = &RISCV_CPU(obj)->env;
 129    set_misa(env, RV32 | RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU);
 130    set_versions(env, USER_VERSION_2_02_0, PRIV_VERSION_1_10_0);
 131    set_resetvec(env, DEFAULT_RSTVEC);
 132    set_feature(env, RISCV_FEATURE_MMU);
 133    set_feature(env, RISCV_FEATURE_PMP);
 134}
 135
 136static void rv32imacu_nommu_cpu_init(Object *obj)
 137{
 138    CPURISCVState *env = &RISCV_CPU(obj)->env;
 139    set_misa(env, RV32 | RVI | RVM | RVA | RVC | RVU);
 140    set_versions(env, USER_VERSION_2_02_0, PRIV_VERSION_1_10_0);
 141    set_resetvec(env, DEFAULT_RSTVEC);
 142    set_feature(env, RISCV_FEATURE_PMP);
 143}
 144
 145#elif defined(TARGET_RISCV64)
 146
 147static void rv64gcsu_priv1_09_1_cpu_init(Object *obj)
 148{
 149    CPURISCVState *env = &RISCV_CPU(obj)->env;
 150    set_misa(env, RV64 | RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU);
 151    set_versions(env, USER_VERSION_2_02_0, PRIV_VERSION_1_09_1);
 152    set_resetvec(env, DEFAULT_RSTVEC);
 153    set_feature(env, RISCV_FEATURE_MMU);
 154    set_feature(env, RISCV_FEATURE_PMP);
 155}
 156
 157static void rv64gcsu_priv1_10_0_cpu_init(Object *obj)
 158{
 159    CPURISCVState *env = &RISCV_CPU(obj)->env;
 160    set_misa(env, RV64 | RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU);
 161    set_versions(env, USER_VERSION_2_02_0, PRIV_VERSION_1_10_0);
 162    set_resetvec(env, DEFAULT_RSTVEC);
 163    set_feature(env, RISCV_FEATURE_MMU);
 164    set_feature(env, RISCV_FEATURE_PMP);
 165}
 166
 167static void rv64imacu_nommu_cpu_init(Object *obj)
 168{
 169    CPURISCVState *env = &RISCV_CPU(obj)->env;
 170    set_misa(env, RV64 | RVI | RVM | RVA | RVC | RVU);
 171    set_versions(env, USER_VERSION_2_02_0, PRIV_VERSION_1_10_0);
 172    set_resetvec(env, DEFAULT_RSTVEC);
 173    set_feature(env, RISCV_FEATURE_PMP);
 174}
 175
 176#endif
 177
 178static ObjectClass *riscv_cpu_class_by_name(const char *cpu_model)
 179{
 180    ObjectClass *oc;
 181    char *typename;
 182    char **cpuname;
 183
 184    cpuname = g_strsplit(cpu_model, ",", 1);
 185    typename = g_strdup_printf(RISCV_CPU_TYPE_NAME("%s"), cpuname[0]);
 186    oc = object_class_by_name(typename);
 187    g_strfreev(cpuname);
 188    g_free(typename);
 189    if (!oc || !object_class_dynamic_cast(oc, TYPE_RISCV_CPU) ||
 190        object_class_is_abstract(oc)) {
 191        return NULL;
 192    }
 193    return oc;
 194}
 195
 196static void riscv_cpu_dump_state(CPUState *cs, FILE *f,
 197    fprintf_function cpu_fprintf, int flags)
 198{
 199    RISCVCPU *cpu = RISCV_CPU(cs);
 200    CPURISCVState *env = &cpu->env;
 201    int i;
 202
 203    cpu_fprintf(f, " %s " TARGET_FMT_lx "\n", "pc      ", env->pc);
 204#ifndef CONFIG_USER_ONLY
 205    cpu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mhartid ", env->mhartid);
 206    cpu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatus ", env->mstatus);
 207    cpu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mip     ",
 208        (target_ulong)atomic_read(&env->mip));
 209    cpu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mie     ", env->mie);
 210    cpu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mideleg ", env->mideleg);
 211    cpu_fprintf(f, " %s " TARGET_FMT_lx "\n", "medeleg ", env->medeleg);
 212    cpu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mtvec   ", env->mtvec);
 213    cpu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mepc    ", env->mepc);
 214    cpu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mcause  ", env->mcause);
 215#endif
 216
 217    for (i = 0; i < 32; i++) {
 218        cpu_fprintf(f, " %s " TARGET_FMT_lx,
 219            riscv_int_regnames[i], env->gpr[i]);
 220        if ((i & 3) == 3) {
 221            cpu_fprintf(f, "\n");
 222        }
 223    }
 224    if (flags & CPU_DUMP_FPU) {
 225        for (i = 0; i < 32; i++) {
 226            cpu_fprintf(f, " %s %016" PRIx64,
 227                riscv_fpr_regnames[i], env->fpr[i]);
 228            if ((i & 3) == 3) {
 229                cpu_fprintf(f, "\n");
 230            }
 231        }
 232    }
 233}
 234
 235static void riscv_cpu_set_pc(CPUState *cs, vaddr value)
 236{
 237    RISCVCPU *cpu = RISCV_CPU(cs);
 238    CPURISCVState *env = &cpu->env;
 239    env->pc = value;
 240}
 241
 242static void riscv_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb)
 243{
 244    RISCVCPU *cpu = RISCV_CPU(cs);
 245    CPURISCVState *env = &cpu->env;
 246    env->pc = tb->pc;
 247}
 248
 249static bool riscv_cpu_has_work(CPUState *cs)
 250{
 251#ifndef CONFIG_USER_ONLY
 252    RISCVCPU *cpu = RISCV_CPU(cs);
 253    CPURISCVState *env = &cpu->env;
 254    /*
 255     * Definition of the WFI instruction requires it to ignore the privilege
 256     * mode and delegation registers, but respect individual enables
 257     */
 258    return (atomic_read(&env->mip) & env->mie) != 0;
 259#else
 260    return true;
 261#endif
 262}
 263
 264void restore_state_to_opc(CPURISCVState *env, TranslationBlock *tb,
 265                          target_ulong *data)
 266{
 267    env->pc = data[0];
 268}
 269
 270static void riscv_cpu_reset(CPUState *cs)
 271{
 272    RISCVCPU *cpu = RISCV_CPU(cs);
 273    RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(cpu);
 274    CPURISCVState *env = &cpu->env;
 275
 276    mcc->parent_reset(cs);
 277#ifndef CONFIG_USER_ONLY
 278    env->priv = PRV_M;
 279    env->mstatus &= ~(MSTATUS_MIE | MSTATUS_MPRV);
 280    env->mcause = 0;
 281    env->pc = env->resetvec;
 282#endif
 283    cs->exception_index = EXCP_NONE;
 284    set_default_nan_mode(1, &env->fp_status);
 285}
 286
 287static void riscv_cpu_disas_set_info(CPUState *s, disassemble_info *info)
 288{
 289#if defined(TARGET_RISCV32)
 290    info->print_insn = print_insn_riscv32;
 291#elif defined(TARGET_RISCV64)
 292    info->print_insn = print_insn_riscv64;
 293#endif
 294}
 295
 296static void riscv_cpu_realize(DeviceState *dev, Error **errp)
 297{
 298    CPUState *cs = CPU(dev);
 299    RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(dev);
 300    Error *local_err = NULL;
 301
 302    cpu_exec_realizefn(cs, &local_err);
 303    if (local_err != NULL) {
 304        error_propagate(errp, local_err);
 305        return;
 306    }
 307
 308    riscv_cpu_register_gdb_regs_for_features(cs);
 309
 310    qemu_init_vcpu(cs);
 311    cpu_reset(cs);
 312
 313    mcc->parent_realize(dev, errp);
 314}
 315
 316static void riscv_cpu_init(Object *obj)
 317{
 318    CPUState *cs = CPU(obj);
 319    RISCVCPU *cpu = RISCV_CPU(obj);
 320
 321    cs->env_ptr = &cpu->env;
 322}
 323
 324static const VMStateDescription vmstate_riscv_cpu = {
 325    .name = "cpu",
 326    .unmigratable = 1,
 327};
 328
 329static void riscv_cpu_class_init(ObjectClass *c, void *data)
 330{
 331    RISCVCPUClass *mcc = RISCV_CPU_CLASS(c);
 332    CPUClass *cc = CPU_CLASS(c);
 333    DeviceClass *dc = DEVICE_CLASS(c);
 334
 335    device_class_set_parent_realize(dc, riscv_cpu_realize,
 336                                    &mcc->parent_realize);
 337
 338    mcc->parent_reset = cc->reset;
 339    cc->reset = riscv_cpu_reset;
 340
 341    cc->class_by_name = riscv_cpu_class_by_name;
 342    cc->has_work = riscv_cpu_has_work;
 343    cc->do_interrupt = riscv_cpu_do_interrupt;
 344    cc->cpu_exec_interrupt = riscv_cpu_exec_interrupt;
 345    cc->dump_state = riscv_cpu_dump_state;
 346    cc->set_pc = riscv_cpu_set_pc;
 347    cc->synchronize_from_tb = riscv_cpu_synchronize_from_tb;
 348    cc->gdb_read_register = riscv_cpu_gdb_read_register;
 349    cc->gdb_write_register = riscv_cpu_gdb_write_register;
 350    cc->gdb_num_core_regs = 33;
 351#if defined(TARGET_RISCV32)
 352    cc->gdb_core_xml_file = "riscv-32bit-cpu.xml";
 353#elif defined(TARGET_RISCV64)
 354    cc->gdb_core_xml_file = "riscv-64bit-cpu.xml";
 355#endif
 356    cc->gdb_stop_before_watchpoint = true;
 357    cc->disas_set_info = riscv_cpu_disas_set_info;
 358#ifdef CONFIG_USER_ONLY
 359    cc->handle_mmu_fault = riscv_cpu_handle_mmu_fault;
 360#else
 361    cc->do_unaligned_access = riscv_cpu_do_unaligned_access;
 362    cc->get_phys_page_debug = riscv_cpu_get_phys_page_debug;
 363#endif
 364#ifdef CONFIG_TCG
 365    cc->tcg_initialize = riscv_translate_init;
 366#endif
 367    /* For now, mark unmigratable: */
 368    cc->vmsd = &vmstate_riscv_cpu;
 369}
 370
 371char *riscv_isa_string(RISCVCPU *cpu)
 372{
 373    int i;
 374    const size_t maxlen = sizeof("rv128") + sizeof(riscv_exts) + 1;
 375    char *isa_str = g_new(char, maxlen);
 376    char *p = isa_str + snprintf(isa_str, maxlen, "rv%d", TARGET_LONG_BITS);
 377    for (i = 0; i < sizeof(riscv_exts); i++) {
 378        if (cpu->env.misa & RV(riscv_exts[i])) {
 379            *p++ = qemu_tolower(riscv_exts[i]);
 380        }
 381    }
 382    *p = '\0';
 383    return isa_str;
 384}
 385
 386typedef struct RISCVCPUListState {
 387    fprintf_function cpu_fprintf;
 388    FILE *file;
 389} RISCVCPUListState;
 390
 391static gint riscv_cpu_list_compare(gconstpointer a, gconstpointer b)
 392{
 393    ObjectClass *class_a = (ObjectClass *)a;
 394    ObjectClass *class_b = (ObjectClass *)b;
 395    const char *name_a, *name_b;
 396
 397    name_a = object_class_get_name(class_a);
 398    name_b = object_class_get_name(class_b);
 399    return strcmp(name_a, name_b);
 400}
 401
 402static void riscv_cpu_list_entry(gpointer data, gpointer user_data)
 403{
 404    RISCVCPUListState *s = user_data;
 405    const char *typename = object_class_get_name(OBJECT_CLASS(data));
 406    int len = strlen(typename) - strlen(RISCV_CPU_TYPE_SUFFIX);
 407
 408    (*s->cpu_fprintf)(s->file, "%.*s\n", len, typename);
 409}
 410
 411void riscv_cpu_list(FILE *f, fprintf_function cpu_fprintf)
 412{
 413    RISCVCPUListState s = {
 414        .cpu_fprintf = cpu_fprintf,
 415        .file = f,
 416    };
 417    GSList *list;
 418
 419    list = object_class_get_list(TYPE_RISCV_CPU, false);
 420    list = g_slist_sort(list, riscv_cpu_list_compare);
 421    g_slist_foreach(list, riscv_cpu_list_entry, &s);
 422    g_slist_free(list);
 423}
 424
 425#define DEFINE_CPU(type_name, initfn)      \
 426    {                                      \
 427        .name = type_name,                 \
 428        .parent = TYPE_RISCV_CPU,          \
 429        .instance_init = initfn            \
 430    }
 431
 432static const TypeInfo riscv_cpu_type_infos[] = {
 433    {
 434        .name = TYPE_RISCV_CPU,
 435        .parent = TYPE_CPU,
 436        .instance_size = sizeof(RISCVCPU),
 437        .instance_init = riscv_cpu_init,
 438        .abstract = true,
 439        .class_size = sizeof(RISCVCPUClass),
 440        .class_init = riscv_cpu_class_init,
 441    },
 442    DEFINE_CPU(TYPE_RISCV_CPU_ANY,              riscv_any_cpu_init),
 443#if defined(TARGET_RISCV32)
 444    DEFINE_CPU(TYPE_RISCV_CPU_RV32GCSU_V1_09_1, rv32gcsu_priv1_09_1_cpu_init),
 445    DEFINE_CPU(TYPE_RISCV_CPU_RV32GCSU_V1_10_0, rv32gcsu_priv1_10_0_cpu_init),
 446    DEFINE_CPU(TYPE_RISCV_CPU_RV32IMACU_NOMMU,  rv32imacu_nommu_cpu_init),
 447    DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E31,       rv32imacu_nommu_cpu_init),
 448    DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_U34,       rv32gcsu_priv1_10_0_cpu_init)
 449#elif defined(TARGET_RISCV64)
 450    DEFINE_CPU(TYPE_RISCV_CPU_RV64GCSU_V1_09_1, rv64gcsu_priv1_09_1_cpu_init),
 451    DEFINE_CPU(TYPE_RISCV_CPU_RV64GCSU_V1_10_0, rv64gcsu_priv1_10_0_cpu_init),
 452    DEFINE_CPU(TYPE_RISCV_CPU_RV64IMACU_NOMMU,  rv64imacu_nommu_cpu_init),
 453    DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E51,       rv64imacu_nommu_cpu_init),
 454    DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_U54,       rv64gcsu_priv1_10_0_cpu_init)
 455#endif
 456};
 457
 458DEFINE_TYPES(riscv_cpu_type_infos)
 459