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 29 static const char riscv_exts[26] = "IMAFDQECLBJTPVNSUHKORWXYZG"; 30 31 const 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 38 const 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 45 const 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 64 const 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 "coprocessor", 78 "host" 79 }; 80 81 typedef struct RISCVCPUInfo { 82 const int bit_widths; 83 const char *name; 84 void (*initfn)(Object *obj); 85 } RISCVCPUInfo; 86 87 static void set_misa(CPURISCVState *env, target_ulong misa) 88 { 89 env->misa = misa; 90 } 91 92 static void set_versions(CPURISCVState *env, int user_ver, int priv_ver) 93 { 94 env->user_ver = user_ver; 95 env->priv_ver = priv_ver; 96 } 97 98 static void set_feature(CPURISCVState *env, int feature) 99 { 100 env->features |= (1ULL << feature); 101 } 102 103 static void set_resetvec(CPURISCVState *env, int resetvec) 104 { 105 #ifndef CONFIG_USER_ONLY 106 env->resetvec = resetvec; 107 #endif 108 } 109 110 static void riscv_any_cpu_init(Object *obj) 111 { 112 CPURISCVState *env = &RISCV_CPU(obj)->env; 113 set_misa(env, RVXLEN | RVI | RVM | RVA | RVF | RVD | RVC | RVU); 114 set_versions(env, USER_VERSION_2_02_0, PRIV_VERSION_1_10_0); 115 set_resetvec(env, DEFAULT_RSTVEC); 116 } 117 118 static void rv32gcsu_priv1_09_1_cpu_init(Object *obj) 119 { 120 CPURISCVState *env = &RISCV_CPU(obj)->env; 121 set_misa(env, RV32 | RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU); 122 set_versions(env, USER_VERSION_2_02_0, PRIV_VERSION_1_09_1); 123 set_resetvec(env, DEFAULT_RSTVEC); 124 set_feature(env, RISCV_FEATURE_MMU); 125 } 126 127 static void rv32gcsu_priv1_10_0_cpu_init(Object *obj) 128 { 129 CPURISCVState *env = &RISCV_CPU(obj)->env; 130 set_misa(env, RV32 | RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU); 131 set_versions(env, USER_VERSION_2_02_0, PRIV_VERSION_1_10_0); 132 set_resetvec(env, DEFAULT_RSTVEC); 133 set_feature(env, RISCV_FEATURE_MMU); 134 } 135 136 static 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 } 143 144 static void rv64gcsu_priv1_09_1_cpu_init(Object *obj) 145 { 146 CPURISCVState *env = &RISCV_CPU(obj)->env; 147 set_misa(env, RV64 | RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU); 148 set_versions(env, USER_VERSION_2_02_0, PRIV_VERSION_1_09_1); 149 set_resetvec(env, DEFAULT_RSTVEC); 150 set_feature(env, RISCV_FEATURE_MMU); 151 } 152 153 static void rv64gcsu_priv1_10_0_cpu_init(Object *obj) 154 { 155 CPURISCVState *env = &RISCV_CPU(obj)->env; 156 set_misa(env, RV64 | RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU); 157 set_versions(env, USER_VERSION_2_02_0, PRIV_VERSION_1_10_0); 158 set_resetvec(env, DEFAULT_RSTVEC); 159 set_feature(env, RISCV_FEATURE_MMU); 160 } 161 162 static void rv64imacu_nommu_cpu_init(Object *obj) 163 { 164 CPURISCVState *env = &RISCV_CPU(obj)->env; 165 set_misa(env, RV64 | RVI | RVM | RVA | RVC | RVU); 166 set_versions(env, USER_VERSION_2_02_0, PRIV_VERSION_1_10_0); 167 set_resetvec(env, DEFAULT_RSTVEC); 168 } 169 170 static const RISCVCPUInfo riscv_cpus[] = { 171 { 96, TYPE_RISCV_CPU_ANY, riscv_any_cpu_init }, 172 { 32, TYPE_RISCV_CPU_RV32GCSU_V1_09_1, rv32gcsu_priv1_09_1_cpu_init }, 173 { 32, TYPE_RISCV_CPU_RV32GCSU_V1_10_0, rv32gcsu_priv1_10_0_cpu_init }, 174 { 32, TYPE_RISCV_CPU_RV32IMACU_NOMMU, rv32imacu_nommu_cpu_init }, 175 { 32, TYPE_RISCV_CPU_SIFIVE_E31, rv32imacu_nommu_cpu_init }, 176 { 32, TYPE_RISCV_CPU_SIFIVE_U34, rv32gcsu_priv1_10_0_cpu_init }, 177 { 64, TYPE_RISCV_CPU_RV64GCSU_V1_09_1, rv64gcsu_priv1_09_1_cpu_init }, 178 { 64, TYPE_RISCV_CPU_RV64GCSU_V1_10_0, rv64gcsu_priv1_10_0_cpu_init }, 179 { 64, TYPE_RISCV_CPU_RV64IMACU_NOMMU, rv64imacu_nommu_cpu_init }, 180 { 64, TYPE_RISCV_CPU_SIFIVE_E51, rv64imacu_nommu_cpu_init }, 181 { 64, TYPE_RISCV_CPU_SIFIVE_U54, rv64gcsu_priv1_10_0_cpu_init }, 182 { 0, NULL, NULL } 183 }; 184 185 static ObjectClass *riscv_cpu_class_by_name(const char *cpu_model) 186 { 187 ObjectClass *oc; 188 char *typename; 189 char **cpuname; 190 191 cpuname = g_strsplit(cpu_model, ",", 1); 192 typename = g_strdup_printf(RISCV_CPU_TYPE_NAME("%s"), cpuname[0]); 193 oc = object_class_by_name(typename); 194 g_strfreev(cpuname); 195 g_free(typename); 196 if (!oc || !object_class_dynamic_cast(oc, TYPE_RISCV_CPU) || 197 object_class_is_abstract(oc)) { 198 return NULL; 199 } 200 return oc; 201 } 202 203 static void riscv_cpu_dump_state(CPUState *cs, FILE *f, 204 fprintf_function cpu_fprintf, int flags) 205 { 206 RISCVCPU *cpu = RISCV_CPU(cs); 207 CPURISCVState *env = &cpu->env; 208 int i; 209 210 cpu_fprintf(f, " %s " TARGET_FMT_lx "\n", "pc ", env->pc); 211 #ifndef CONFIG_USER_ONLY 212 cpu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mhartid ", env->mhartid); 213 cpu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatus ", env->mstatus); 214 cpu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mip ", 215 (target_ulong)atomic_read(&env->mip)); 216 cpu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mie ", env->mie); 217 cpu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mideleg ", env->mideleg); 218 cpu_fprintf(f, " %s " TARGET_FMT_lx "\n", "medeleg ", env->medeleg); 219 cpu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mtvec ", env->mtvec); 220 cpu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mepc ", env->mepc); 221 cpu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mcause ", env->mcause); 222 #endif 223 224 for (i = 0; i < 32; i++) { 225 cpu_fprintf(f, " %s " TARGET_FMT_lx, 226 riscv_int_regnames[i], env->gpr[i]); 227 if ((i & 3) == 3) { 228 cpu_fprintf(f, "\n"); 229 } 230 } 231 for (i = 0; i < 32; i++) { 232 cpu_fprintf(f, " %s %016" PRIx64, 233 riscv_fpr_regnames[i], env->fpr[i]); 234 if ((i & 3) == 3) { 235 cpu_fprintf(f, "\n"); 236 } 237 } 238 } 239 240 static void riscv_cpu_set_pc(CPUState *cs, vaddr value) 241 { 242 RISCVCPU *cpu = RISCV_CPU(cs); 243 CPURISCVState *env = &cpu->env; 244 env->pc = value; 245 } 246 247 static void riscv_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb) 248 { 249 RISCVCPU *cpu = RISCV_CPU(cs); 250 CPURISCVState *env = &cpu->env; 251 env->pc = tb->pc; 252 } 253 254 static bool riscv_cpu_has_work(CPUState *cs) 255 { 256 #ifndef CONFIG_USER_ONLY 257 RISCVCPU *cpu = RISCV_CPU(cs); 258 CPURISCVState *env = &cpu->env; 259 /* 260 * Definition of the WFI instruction requires it to ignore the privilege 261 * mode and delegation registers, but respect individual enables 262 */ 263 return (atomic_read(&env->mip) & env->mie) != 0; 264 #else 265 return true; 266 #endif 267 } 268 269 void restore_state_to_opc(CPURISCVState *env, TranslationBlock *tb, 270 target_ulong *data) 271 { 272 env->pc = data[0]; 273 } 274 275 static void riscv_cpu_reset(CPUState *cs) 276 { 277 RISCVCPU *cpu = RISCV_CPU(cs); 278 RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(cpu); 279 CPURISCVState *env = &cpu->env; 280 281 mcc->parent_reset(cs); 282 #ifndef CONFIG_USER_ONLY 283 env->priv = PRV_M; 284 env->mstatus &= ~(MSTATUS_MIE | MSTATUS_MPRV); 285 env->mcause = 0; 286 env->pc = env->resetvec; 287 #endif 288 cs->exception_index = EXCP_NONE; 289 set_default_nan_mode(1, &env->fp_status); 290 } 291 292 static void riscv_cpu_disas_set_info(CPUState *s, disassemble_info *info) 293 { 294 #if defined(TARGET_RISCV32) 295 info->print_insn = print_insn_riscv32; 296 #elif defined(TARGET_RISCV64) 297 info->print_insn = print_insn_riscv64; 298 #endif 299 } 300 301 static void riscv_cpu_realize(DeviceState *dev, Error **errp) 302 { 303 CPUState *cs = CPU(dev); 304 RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(dev); 305 Error *local_err = NULL; 306 307 cpu_exec_realizefn(cs, &local_err); 308 if (local_err != NULL) { 309 error_propagate(errp, local_err); 310 return; 311 } 312 313 qemu_init_vcpu(cs); 314 cpu_reset(cs); 315 316 mcc->parent_realize(dev, errp); 317 } 318 319 static void riscv_cpu_init(Object *obj) 320 { 321 CPUState *cs = CPU(obj); 322 RISCVCPU *cpu = RISCV_CPU(obj); 323 324 cs->env_ptr = &cpu->env; 325 } 326 327 static const VMStateDescription vmstate_riscv_cpu = { 328 .name = "cpu", 329 .unmigratable = 1, 330 }; 331 332 static void riscv_cpu_class_init(ObjectClass *c, void *data) 333 { 334 RISCVCPUClass *mcc = RISCV_CPU_CLASS(c); 335 CPUClass *cc = CPU_CLASS(c); 336 DeviceClass *dc = DEVICE_CLASS(c); 337 338 mcc->parent_realize = dc->realize; 339 dc->realize = riscv_cpu_realize; 340 341 mcc->parent_reset = cc->reset; 342 cc->reset = riscv_cpu_reset; 343 344 cc->class_by_name = riscv_cpu_class_by_name; 345 cc->has_work = riscv_cpu_has_work; 346 cc->do_interrupt = riscv_cpu_do_interrupt; 347 cc->cpu_exec_interrupt = riscv_cpu_exec_interrupt; 348 cc->dump_state = riscv_cpu_dump_state; 349 cc->set_pc = riscv_cpu_set_pc; 350 cc->synchronize_from_tb = riscv_cpu_synchronize_from_tb; 351 cc->gdb_read_register = riscv_cpu_gdb_read_register; 352 cc->gdb_write_register = riscv_cpu_gdb_write_register; 353 cc->gdb_num_core_regs = 65; 354 cc->gdb_stop_before_watchpoint = true; 355 cc->disas_set_info = riscv_cpu_disas_set_info; 356 #ifdef CONFIG_USER_ONLY 357 cc->handle_mmu_fault = riscv_cpu_handle_mmu_fault; 358 #else 359 cc->do_unaligned_access = riscv_cpu_do_unaligned_access; 360 cc->get_phys_page_debug = riscv_cpu_get_phys_page_debug; 361 #endif 362 #ifdef CONFIG_TCG 363 cc->tcg_initialize = riscv_translate_init; 364 #endif 365 /* For now, mark unmigratable: */ 366 cc->vmsd = &vmstate_riscv_cpu; 367 } 368 369 static void cpu_register(const RISCVCPUInfo *info) 370 { 371 TypeInfo type_info = { 372 .name = info->name, 373 .parent = TYPE_RISCV_CPU, 374 .instance_size = sizeof(RISCVCPU), 375 .instance_init = info->initfn, 376 }; 377 378 type_register(&type_info); 379 } 380 381 static const TypeInfo riscv_cpu_type_info = { 382 .name = TYPE_RISCV_CPU, 383 .parent = TYPE_CPU, 384 .instance_size = sizeof(RISCVCPU), 385 .instance_init = riscv_cpu_init, 386 .abstract = false, 387 .class_size = sizeof(RISCVCPUClass), 388 .class_init = riscv_cpu_class_init, 389 }; 390 391 char *riscv_isa_string(RISCVCPU *cpu) 392 { 393 int i; 394 size_t maxlen = 5 + ctz32(cpu->env.misa); 395 char *isa_string = g_new0(char, maxlen); 396 snprintf(isa_string, maxlen, "rv%d", TARGET_LONG_BITS); 397 for (i = 0; i < sizeof(riscv_exts); i++) { 398 if (cpu->env.misa & RV(riscv_exts[i])) { 399 isa_string[strlen(isa_string)] = riscv_exts[i] - 'A' + 'a'; 400 401 } 402 } 403 return isa_string; 404 } 405 406 void riscv_cpu_list(FILE *f, fprintf_function cpu_fprintf) 407 { 408 const RISCVCPUInfo *info = riscv_cpus; 409 410 while (info->name) { 411 if (info->bit_widths & TARGET_LONG_BITS) { 412 (*cpu_fprintf)(f, "%s\n", info->name); 413 } 414 info++; 415 } 416 } 417 418 static void riscv_cpu_register_types(void) 419 { 420 const RISCVCPUInfo *info = riscv_cpus; 421 422 type_register_static(&riscv_cpu_type_info); 423 424 while (info->name) { 425 if (info->bit_widths & TARGET_LONG_BITS) { 426 cpu_register(info); 427 } 428 info++; 429 } 430 } 431 432 type_init(riscv_cpu_register_types) 433