sev/i386: add support to LAUNCH_MEASURE command
[qemu/ar7.git] / target / riscv / cpu.c
blob4851890844ea360ab1f4312f7633f0d627d5882a
1 /*
2 * QEMU RISC-V CPU
4 * Copyright (c) 2016-2017 Sagar Karandikar, sagark@eecs.berkeley.edu
5 * Copyright (c) 2017-2018 SiFive, Inc.
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.
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.
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/>.
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"
27 /* RISC-V CPU definitions */
29 static const char riscv_exts[26] = "IMAFDQECLBJTPVNSUHKORWXYZG";
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 "
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"
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"
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"
81 typedef struct RISCVCPUInfo {
82 const int bit_widths;
83 const char *name;
84 void (*initfn)(Object *obj);
85 } RISCVCPUInfo;
87 static void set_misa(CPURISCVState *env, target_ulong misa)
89 env->misa = misa;
92 static void set_versions(CPURISCVState *env, int user_ver, int priv_ver)
94 env->user_ver = user_ver;
95 env->priv_ver = priv_ver;
98 static void set_feature(CPURISCVState *env, int feature)
100 env->features |= (1ULL << feature);
103 static void set_resetvec(CPURISCVState *env, int resetvec)
105 #ifndef CONFIG_USER_ONLY
106 env->resetvec = resetvec;
107 #endif
110 static void riscv_any_cpu_init(Object *obj)
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);
118 static void rv32gcsu_priv1_09_1_cpu_init(Object *obj)
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);
127 static void rv32gcsu_priv1_10_0_cpu_init(Object *obj)
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);
136 static void rv32imacu_nommu_cpu_init(Object *obj)
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);
144 static void rv64gcsu_priv1_09_1_cpu_init(Object *obj)
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);
153 static void rv64gcsu_priv1_10_0_cpu_init(Object *obj)
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);
162 static void rv64imacu_nommu_cpu_init(Object *obj)
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);
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 }
185 static ObjectClass *riscv_cpu_class_by_name(const char *cpu_model)
187 ObjectClass *oc;
188 char *typename;
189 char **cpuname;
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;
200 return oc;
203 static void riscv_cpu_dump_state(CPUState *cs, FILE *f,
204 fprintf_function cpu_fprintf, int flags)
206 RISCVCPU *cpu = RISCV_CPU(cs);
207 CPURISCVState *env = &cpu->env;
208 int i;
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
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");
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");
240 static void riscv_cpu_set_pc(CPUState *cs, vaddr value)
242 RISCVCPU *cpu = RISCV_CPU(cs);
243 CPURISCVState *env = &cpu->env;
244 env->pc = value;
247 static void riscv_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb)
249 RISCVCPU *cpu = RISCV_CPU(cs);
250 CPURISCVState *env = &cpu->env;
251 env->pc = tb->pc;
254 static bool riscv_cpu_has_work(CPUState *cs)
256 #ifndef CONFIG_USER_ONLY
257 RISCVCPU *cpu = RISCV_CPU(cs);
258 CPURISCVState *env = &cpu->env;
260 * Definition of the WFI instruction requires it to ignore the privilege
261 * mode and delegation registers, but respect individual enables
263 return (atomic_read(&env->mip) & env->mie) != 0;
264 #else
265 return true;
266 #endif
269 void restore_state_to_opc(CPURISCVState *env, TranslationBlock *tb,
270 target_ulong *data)
272 env->pc = data[0];
275 static void riscv_cpu_reset(CPUState *cs)
277 RISCVCPU *cpu = RISCV_CPU(cs);
278 RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(cpu);
279 CPURISCVState *env = &cpu->env;
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);
292 static void riscv_cpu_disas_set_info(CPUState *s, disassemble_info *info)
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
301 static void riscv_cpu_realize(DeviceState *dev, Error **errp)
303 CPUState *cs = CPU(dev);
304 RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(dev);
305 Error *local_err = NULL;
307 cpu_exec_realizefn(cs, &local_err);
308 if (local_err != NULL) {
309 error_propagate(errp, local_err);
310 return;
313 qemu_init_vcpu(cs);
314 cpu_reset(cs);
316 mcc->parent_realize(dev, errp);
319 static void riscv_cpu_init(Object *obj)
321 CPUState *cs = CPU(obj);
322 RISCVCPU *cpu = RISCV_CPU(obj);
324 cs->env_ptr = &cpu->env;
327 static const VMStateDescription vmstate_riscv_cpu = {
328 .name = "cpu",
329 .unmigratable = 1,
332 static void riscv_cpu_class_init(ObjectClass *c, void *data)
334 RISCVCPUClass *mcc = RISCV_CPU_CLASS(c);
335 CPUClass *cc = CPU_CLASS(c);
336 DeviceClass *dc = DEVICE_CLASS(c);
338 mcc->parent_realize = dc->realize;
339 dc->realize = riscv_cpu_realize;
341 mcc->parent_reset = cc->reset;
342 cc->reset = riscv_cpu_reset;
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;
369 static void cpu_register(const RISCVCPUInfo *info)
371 TypeInfo type_info = {
372 .name = info->name,
373 .parent = TYPE_RISCV_CPU,
374 .instance_size = sizeof(RISCVCPU),
375 .instance_init = info->initfn,
378 type_register(&type_info);
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,
391 char *riscv_isa_string(RISCVCPU *cpu)
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';
403 return isa_string;
406 void riscv_cpu_list(FILE *f, fprintf_function cpu_fprintf)
408 const RISCVCPUInfo *info = riscv_cpus;
410 while (info->name) {
411 if (info->bit_widths & TARGET_LONG_BITS) {
412 (*cpu_fprintf)(f, "%s\n", info->name);
414 info++;
418 static void riscv_cpu_register_types(void)
420 const RISCVCPUInfo *info = riscv_cpus;
422 type_register_static(&riscv_cpu_type_info);
424 while (info->name) {
425 if (info->bit_widths & TARGET_LONG_BITS) {
426 cpu_register(info);
428 info++;
432 type_init(riscv_cpu_register_types)