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